CommonJs 模块系统中“module.exports”和“exports”之间的区别

2022-08-29 23:54:17

在此页(http://docs.nodejitsu.com/articles/getting-started/what-is-require)上,它指出“如果要将 export 对象设置为函数或新对象,则必须使用 module.exports 对象。

我的问题是为什么。

// right
module.exports = function () {
  console.log("hello world")
}
// wrong
exports = function () {
  console.log("hello world")
}

I console.logged 结果 (),第一个是 第二个是 。result=require(example.js)[Function]{}

您能解释一下它背后的原因吗?我在这里阅读了这篇文章:module.exports vs exports in Node.js 。这是有帮助的,但没有解释为什么以这种方式设计它。如果直接退回出口的参考,是否会有问题?


答案 1

module是具有属性的普通 JavaScript 对象。 是一个普通的 JavaScript 变量,恰好设置为 。在文件末尾,node.js基本上会“返回”到函数。在 Node 中查看 JS 文件的简化方法可能是:exportsexportsmodule.exportsmodule.exportsrequire

var module = { exports: {} };
var exports = module.exports;

// your code

return module.exports;

如果你在 上设置一个属性,比如 ,那也会设置,因为对象在 JavaScript 中作为引用传递,这意味着如果你为同一个对象设置多个变量,它们都是同一个对象;所以然后和是同一个对象。
但是,如果设置为新对象,它将不再设置为 ,因此并且不再是同一个对象。exportsexports.a = 9;module.exports.aexportsmodule.exportsexportsmodule.exportsexportsmodule.exports


答案 2

Renee的答案得到了很好的解释。通过示例对答案进行补充:

Node对您的文件执行了很多事情,其中一个重要的操作是包装文件。返回 nodejs 内部源代码 “module.exports”。让我们退后一步,了解包装器。假设您有

问候.js

var greet = function () {
   console.log('Hello World');
};

module.exports = greet;

上面的代码被包装为IIFE(立即调用的函数表达式)在nodejs源代码中,如下所示:

(function (exports, require, module, __filename, __dirname) { //add by node

      var greet = function () {
         console.log('Hello World');
      };

      module.exports = greet;

}).apply();                                                  //add by node

return module.exports;                                      //add by node

并调用上述函数 (.apply()) 并返回 module.export。此时 module.export 和 export 指向同一引用。

现在,想象一下你把问候语重写.js

exports = function () {
   console.log('Hello World');
};
console.log(exports);
console.log(module.exports);

输出将为

[Function]
{}

原因是:module.exports是一个空对象。我们没有对module.exports设置任何东西,而是设置了export = function().....在新问候中.js。因此,module.exports 是空的。

从技术上讲,导出和module.export应该指向相同的引用(这是正确的!!)。但是我们在分配函数()时使用“=”....以导出,这将在内存中创建另一个对象。因此,module.export 和 export 产生不同的结果。当涉及到出口时,我们不能覆盖它。

现在,想象一下你重写(这被称为突变)问候.js(指蕾妮答案)作为

exports.a = function() {
    console.log("Hello");
}

console.log(exports);
console.log(module.exports);

输出将为

{ a: [Function] }
{ a: [Function] }

如您所见,module.export 和 export 指向同一个引用,这是一个函数。如果在导出时设置了属性,那么它将在 module.export 上设置,因为在 JS 中,对象是通过引用传递的。

结论是始终使用module.exports以避免混淆。希望这有帮助。快乐编码:)