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

2020/10/07 01:20 · javascript ·  · 0评论

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

我的问题是为什么。

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

我console.logged结果(result=require(example.js))和第[Function]一个是{}

您能否解释其背后的原因?我在这里阅读了这篇文章:Node.js中的module.exports与export它很有帮助,但没有说明采用这种方式进行设计的原因。如果直接返回出口参考书会不会有问题?

module是具有exports属性的普通JavaScript对象exports是一个普通的JavaScript变量,碰巧设置为module.exports在文件末尾,node.js基本上将“返回”module.exportsrequire函数。在Node中查看JS文件的一种简化方法是:

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

// your code

return module.exports;

如果在上设置exports,如exports.a = 9;,该属性也会设置module.exports.a,因为对象是作为JavaScript中的引用传递的,这意味着如果将多个变量设置为同一对象,则它们都是同一对象;因此,exportsmodule.exports是相同的对象。

但是,如果你设置
exports新的东西,这将不再被设定为module.exports,所以exportsmodule.exports不再是同一个对象。

蕾妮的答案得到了很好的解释。除示例外,还提供答案:

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

greet.js

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

module.exports = greet;

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

(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.exports。这时module.exports和export指向相同的引用。

现在,假设您将greet.js重新编写为

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

输出将是

[Function]
{}

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

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

现在,假设您将greet.js(指的是Renee答案)重写为

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

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

输出将是

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

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

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

此外,可能有助于理解的一件事:

math.js

this.add = function (a, b) {
    return a + b;
};

client.js

var math = require('./math');
console.log(math.add(2,2); // 4;

很好,在这种情况下:

console.log(this === module.exports); // true
console.log(this === exports); // true
console.log(module.exports === exports); // true

因此,默认情况下,“ this”实际上等于module.exports。

但是,如果将实现更改为:

math.js

var add = function (a, b) {
    return a + b;
};

module.exports = {
    add: add
};

在这种情况下,它可以正常工作,但是,“ this”不再等于module.exports,因为创建了一个新对象。

console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false

现在,require将返回的是模块内部定义的内容。exports,而不是this或exports。

另一种方法是:

math.js

module.exports.add = function (a, b) {
    return a + b;
};

要么:

math.js

exports.add = function (a, b) {
    return a + b;
};

刘若英的约之间的关系答案exportsmodule.exports是相当清楚的,它是所有关于JavaScript的引用。只需添加:

我们在许多节点模块中看到了这一点:

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

这将确保即使我们更改了module.exports,我们仍然可以通过使这两个变量指向同一对象来使用export。

myTest.js

module.exports.get = function () {};

exports.put = function () {};

console.log(module.exports)
// output: { get: [Function], put: [Function] }

exports并且module.exports是相同的,并且是对同一对象的引用。您可以根据需要通过两种方式添加属性。

本文地址:http://javascript.askforanswer.com/commonjsmokuaixitongzhong-module-exportshe-exportszhijiandequbie.html
文章标签: ,   ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!