3

CommonJSモジュールは、次のイディオムを使用して定義されているのが一般的です。

(function() {
   var logThis = function() { console.log(this); }
   module.exports = logThis;
}).call(this);

たとえば、Underscore.jsはこれを行います。

私はちょうど30分を同僚と話し合って、なぜ彼らがでクロージャーを呼び出すのかを話し合っていcall(this)ます。これによりthis、クロージャ内の値は、グローバルオブジェクトに設定されるのではなく、呼び出し元から継承されます。ただし、これをNode.jsでテストした場合this、モジュール内の値は、次のようにロードして実行した場合でも、常にグローバルオブジェクトでした。

var bar = {};
bar.foo = function() { var foo = require("./foo"); foo(); }

コンソールにオブジェクトが表示されることを本当に期待していましたbarが、実際にはグローバルオブジェクトが表示されます。その後、Underscore.jsなどのモジュールがWebコンテキストでも使用されていることが原因である可能性があることに気付きました。ただし、その場合は<script>タグがロードされるためthis、とにかく常にグローバルオブジェクトと等しくなります。

何が得られますか?この構成を使用する理由は確かにありますが、モジュールがNode.jsで使用されているか、Webページで使用されているかにかかわらず、この特定のケースで実際的な違いはわかりません。

更新:明確にするために、これが違いを生む可能性のあるいくつかのケースを考えることができます。たとえば、私が言う場合:

var bar = {}
var foo = require("./foo");
bar.foo = foo;
bar.foo();

(元の例を修正してくれた@Pointyに感謝します。)

モジュール内のクロージャは、が呼び出されたときに評価されることを期待します。つまり、モジュール内require()の値はグローバルオブジェクトにバインドされ、「バー」のメンバーとして呼び出されてthisもコンソールに書き込まれます。 foo()" 物体。ただし、この例でも、コンソールに「bar」オブジェクトが表示されています。私はそれthisが私が期待したように閉鎖に縛られていないと思いますか?

一言で言えば、Underscore.jsのようなモジュールが、Node.jsまたはWebページのいずれかで、fn.call(this)だけでなくで呼び出されたクロージャーにラップされているために、異なる動作をする1つの例を探しています。fn()

4

1 に答える 1

4

「bar.foo」内の「foo」への呼び出しはコンテキストなしで行われるため、グローバル コンテキストが使用されます。this「バー」を参照する関数内にあるという事実は関係ありません。それは JavaScript の仕組みではありません。重要なのは、関数がどこで呼び出されるかではなく、関数がどのように呼び出されるかだけです。

「bar.foo」が次のようになっている場合:

bar.foo = function() { require("./foo"); foo.call(this); }

コンソールに「バー」が表示されます。または、次のようにすることもできます。

var bar = {};
require("./foo");
bar.foo = foo; 

次に呼び出すbar.foo()と、「バー」オブジェクトもログに記録されます。(それは Node で本当に機能しますか? つまりrequire()、オブジェクトが返され、それがグローバル スコープにあるだけではないと思いました。しかし、私は Node の初心者です。)

編集— 更新していただきありがとうございます。したがって、私の例は次のように修正されます。まず、モジュールは次のようになると思います。

(function() {
   var logThis = function() { console.log(this); }
   module.exports.logThis = logThis;
}).call(this);

つまり、「logThis」関数を探索したいので、名前付きプロパティとして「exports」オブジェクトにバインドする必要があると思います。

それで:

var bar = {};
var foo = require("./foo");
// At this point, foo.logThis is the function 
bar.foo = foo.logThis;
// Now the "foo" property of "bar" is a reference to the same function
bar.foo(); // logs the "bar" object

var fee = { fie: foo.logThis };
fee.fie(); // logs the "fee" object
于 2012-08-01T16:45:44.440 に答える