为什么在 a.js 中看不到 b.js 中定义的变量,尽管包括前者?

Why can't I see a variable defined in b.js within a.js, despite including the former?

这是b.js

var something = "hooorraaaaay!!!";

这是a.js

require( './b.js' );

console.log(something);

为什么 somethinga.js 中没有被识别。我知道它是用 var 声明的,但我的理解是任何在函数外声明的变量都应该是全局变量。那为什么这不起作用?

让我假设您正在使用 node.js 从 require 函数判断。

node.js 将每个文件包装在其自己的范围内。这与 var 关键字的使用无关。 node.js 中的每个文件都称为一个模块。

现在假设你想包含一个模块,require,你用对了。 但是因为你的模块不导出任何东西,当它被包含在其他模块中时它是无用的。

因此,在 b.js 文件的末尾,添加以下行:

module.exports.something = something;

现在我们终于可以使用导出的变量了:

var b = require('./b.js');
console.log('Something is : ' + b.something);

每个节点模块都在自己的范围内。默认情况下,模块 a 中的任何内容对模块 b 都是可见的。在模块上执行 require() 与包含源代码不同。它加载文件运行代码,然后外界唯一可用的是:

  1. 通过分配给 module.exports.
  2. 从模块中显式导出的任何函数或属性
  3. 明确分配给节点中 global 对象的任何函数或属性。

所以,如果你想让 b.js 中的东西暴露给外界,你可以这样做:

// b.js

module.exports.callMe = function() {
    console.log("I'm in module b");
}

然后,在 a.js 中,您可以这样做:

// a.js
var b = require('./b.js');
b.callMe();

这就是模块系统在 node.js 中的工作方式。它与仅在浏览器网页中包含 <script> 标记有很大不同。您可以在这些参考资料中阅读有关模块系统的更多信息:

Understanding module.exports and exports in Node.js

What is the purpose of Node.js module.exports and how do you use it?

Node.js Handbook - How require() Actually Works


在内部,node.js 加载模块代码,然后将其插入到包装函数中。因此,节点模块中的每个顶级变量实际上只是该模块函数中的局部变量。这就是默认情况下没有全局声明或共享任何内容的原因。这是故意这样做的,这样每个模块都有自己的私有区域来存储它的状态,并且默认情况下不会干扰任何其他模块的变量。

然后您只显式导出要创建 public 的 property/function 接口,即便如此,它们仍然不会导出为 public 符号,因此它们不会与任何内容发生冲突否则。

所以,上面的 b.js 代码实际上在 node.js 运行时变成了这个:

(function (exports, module, require, __filename, __dirname){
    module.exports.callMe = function() {
        console.log("I'm in module b");
    }
})(...);

(...) 包含传递给模块的实际变量。