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

标签 javascript node.js commonjs

常见的 CommonJS 模块是使用以下习惯用法定义的:

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

Underscore.js ,例如,这样做。

我只花了半个小时与一位同事讨论为什么他们使用 call(this) 调用闭包。这将导致闭包内 this 的值从调用者继承,而不是设置为全局对象。然而,当我在 Node.js 中测试它时,模块内 this 的值始终是全局对象,即使我像这样加载和运行它也是如此:

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

我真的很期待在控制台中看到 bar 对象,但实际上我看到的是全局对象。然后我想到这可能是因为像 Underscore.js 这样的模块也在网络上下文中使用。但在那种情况下,它会加载一个 <script> 标签,所以 this 将始终等于全局对象。

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

更新:澄清一下,我能想到一些这可以发挥作用的案例。例如,如果我说:

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

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

我希望在调用 require() 时评估模块中的闭包,这意味着其中的 this 的值将绑定(bind)到全局对象,即使 foo() 随后作为“bar”对象的成员被调用,它也会被写入控制台。但是,即使在这个例子中,我也在控制台中看到了“bar”对象。我猜 this 没有像我预期的那样绑定(bind)到闭包?

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

最佳答案

您在“bar.foo”中对“foo”的调用是在没有任何上下文的情况下进行的,因此使用了全局上下文。它在 this 引用“bar”的函数内部这一事实无关紧要;那不是 JavaScript 的工作方式。唯一重要的是如何调用函数,而不是在哪里调用它,换句话说。

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

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

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

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”函数,所以它需要作为命名属性绑定(bind)到“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

关于javascript - 定义 CommonJS 模块时的 fn.call(this) 与 fn(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11763819/

相关文章:

javascript - AngularJS 中的 ng-repeat 不起作用,为什么?

javascript - 我可以为所有 AJAX 请求设置全局 header 吗?

node.js - 检查 semver 是否正确

javascript - 尝试使用 Node.js 和 mysql javascript 客户端连接到 MySQL 数据库

javascript - Closure Compiler 可以构建 CommonJS 模块吗

javascript - 如何在 CommonJS 项目中包含 Epson SDK for JavaScript

reactjs - CommonJS 导入与 ES6 导入

javascript - PHP 和 Javascript toast

javascript - 如何在 UI 中与 React JS 一起实现无限滚动?

node.js - 自耕农发电机;这些错误是什么意思?