繁体   English   中英

定义CommonJS模块时fn.call(this)与fn()

[英]fn.call(this) versus fn() when defining a CommonJS module

通常使用以下习语定义CommonJS模块:

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

例如, Underscore.js就是这样做的。

我只花了半个小时与同事讨论为什么他们通过call(this)调用关闭call(this) 这将导致闭包内的this值从调用者继承,而不是设置为全局对象。 然而,当我在测试的Node.js这样,值this模块内部总是全局对象,甚至当我加载并运行它是这样的:

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

我真的希望在控制台中看到bar对象,但实际上我看到了全局对象。 然后我想到这可能是因为像Underscore.js这样的模块也用在Web上下文中。 但在这种情况下,它会用<script>标记加载所以this将永远是等于全局对象呢。

是什么赋予了? 我确信使用这个结构是有原因的,但是在这个特殊情况下我看不出该模块是在Node.js还是在网页中使用的实际区别。

更新:为了澄清,我可以想到一些可能会产生影响的案例。 例如,如果我说:

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

(感谢@Pointy纠正我原来的例子。)

我希望在模块中关闭时进行评估require()被调用,这意味着价值this里面将它绑定到全局对象,这将被写入即使控制台foo()然后调用作为“酒吧”对象的成员。 但是,即使在此示例中,我也在控制台中看到“bar”对象。 我想this不像我预期的那样受限于封闭?

简而言之,我正在寻找一个示例,其中像fn.call(this)的模块将具有不同的行为,因为它被包装在用fn.call(this)调用的闭包中,而不仅仅是fn() ,无论是在Node.js中还是在网页中。

您在“bar.foo”中对“foo”的调用是在没有任何上下文的情况下进行的,因此使用了全局上下文。 事实上,它在一个函数中, this指的是“bar”是不相关的; 这不是JavaScript的工作原理。 唯一重要的事情是该函数的调用,而不是在那里的调用,换句话说。

如果“bar.foo”看起来像这样:

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

然后你会在控制台中看到“bar”。 或者,你可以这样做:

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

然后调用bar.foo()也会记录“bar”对象。 (这确实在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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM