Javascript 区别于;“出口”模块;及;“出口”;在CommonJs模块系统中

Javascript 区别于;“出口”模块;及;“出口”;在CommonJs模块系统中,javascript,node.js,commonjs,Javascript,Node.js,Commonjs,在此页()上,它声明“如果要将exports对象设置为函数或新对象,则必须使用module.exports对象。” 我的问题是为什么 // right module.exports = function () { console.log("hello world") } // wrong exports = function () { console.log("hello world") } I console.log记录结果(result=re

在此页()上,它声明“如果要将exports对象设置为函数或新对象,则必须使用module.exports对象。”

我的问题是为什么

// right
module.exports = function () {
  console.log("hello world")
}
// wrong
exports = function () {
  console.log("hello world")
}
I console.log记录结果(
result=require(example.js)
),第一个是
[Function]
,第二个是
{}


你能解释一下背后的原因吗?我在这里读了帖子:。这是有帮助的,但没有解释为什么它是这样设计的。如果直接返回导出的引用,是否会出现问题?

模块
是一个带有
导出
属性的普通JavaScript对象
exports
是一个普通JavaScript变量,恰好设置为
module.exports
。 在文件末尾,node.js基本上会“返回”模块。将导出到
require
函数。在节点中查看JS文件的简化方法如下:

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

// your code

return module.exports;
如果在
exports
上设置属性,如
exports.a=9
,这将设置
模块.exports.a
,因为对象在JavaScript中作为引用传递,这意味着如果您将多个变量设置为同一个对象,那么它们都是同一个对象;因此,
导出
模块。导出
是同一个对象。

但是如果将
导出
设置为新的对象,它将不再设置为
模块。导出
,因此
导出
模块。导出
不再是同一个对象。

模块
是一个具有
导出
属性的普通JavaScript对象
exports
是一个普通JavaScript变量,恰好设置为
module.exports
。 在文件末尾,node.js基本上会“返回”模块。将导出到
require
函数。在节点中查看JS文件的简化方法如下:

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

// your code

return module.exports;
如果在
exports
上设置属性,如
exports.a=9
,这将设置
模块.exports.a
,因为对象在JavaScript中作为引用传递,这意味着如果您将多个变量设置为同一个对象,那么它们都是同一个对象;因此,
导出
模块。导出
是同一个对象。

但是如果您将
导出
设置为新对象,它将不再设置为
模块。导出
,因此
导出
模块。导出
不再是同一个对象。

Rene关于
导出
模块。导出
之间关系的回答非常清楚,这都是关于javascript引用的。我只想补充一点:

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

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


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

Rene关于
exports
module.exports
之间关系的回答非常清楚,都是关于javascript引用的。我只想补充一点:

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

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


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

还有一点可以帮助理解:

math.js

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

module.exports = {
    add: add
};
module.exports.add = function (a, b) {
    return a + b;
};
exports.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

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

module.exports = {
    add: add
};
module.exports.add = function (a, b) {
    return a + b;
};
exports.add = function (a, b) {
    return a + b;
};
在这种情况下,它可以正常工作,但是,“this”不再等于module.exports,因为创建了一个新对象

console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
现在,require返回的是module.exports中定义的内容,不再是this或exports

另一种方法是:

math.js

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

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

math.js

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

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

还有一件事可能有助于理解:

math.js

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

module.exports = {
    add: add
};
module.exports.add = function (a, b) {
    return a + b;
};
exports.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

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

module.exports = {
    add: add
};
module.exports.add = function (a, b) {
    return a + b;
};
exports.add = function (a, b) {
    return a + b;
};
在这种情况下,它可以正常工作,但是,“this”不再等于module.exports,因为创建了一个新对象

console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
现在,require返回的是module.exports中定义的内容,不再是this或exports

另一种方法是:

math.js

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

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

math.js

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

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

蕾妮的答案解释得很好。用一个例子补充答案:

节点对您的文件执行很多操作,其中一个重要的操作是包装您的文件。在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和exports指向同一引用

现在,想象你在写 将.js作为

exports = function () {
   console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
输出将是

[Function]
{}
原因是:module.exports是空对象。我们没有将任何内容设置为module.exports,而是设置exports=function()。。。。。在new greet.js中。因此,module.exports为空

技术上,导出和module.exports应该指向相同的引用(这是正确的!!)。但是我们在赋值函数()时使用“=”。。。。导出,这将在内存中创建另一个对象。因此,module.exports和exports产生不同的结果。说到出口,我们不能忽略它

现在,想象你重新编写(这称为变异) greet.js(指Renee answer)作为

输出将是

{ a: [Function] }
{ a: [Function] }
如您所见,module.exports和exports指向相同的位置