module.exports"和“;exports"在CommonJs模块系统中
Difference between "module.exports" and "exports" in the CommonJs Module System
在这个页面(http://docs.nodejitsu.com/articles/getting-started/what-is-require)上,它声明"如果您想将exports对象设置为一个函数或一个新对象,则必须使用该模块。出口对象!"
我的问题是为什么。
// right
module.exports = function () {
console.log("hello world")
}
// wrong
exports = function () {
console.log("hello world")
}
我控制台。记录结果(result=require(example.js)
),第一个是[Function]
,第二个是{}
。
你能解释一下背后的原因吗?我在这里读了这篇文章:模块。Node.js中的exports和exports。这是有帮助的,但并没有解释为什么它是这样设计的。如果直接退回出口的引用会有问题吗?
module
是一个具有exports
属性的普通JavaScript对象。exports
是一个普通的JavaScript变量,恰好被设置为module.exports
。在文件的末尾,node.js基本上会将module.exports
"返回"到require
函数。在Node中查看JS文件的一种简化方法是:
var module = { exports: {} };
var exports = module.exports;
// your code
return module.exports;
如果你在exports
上设置了一个属性,比如exports.a = 9;
,那也会设置module.exports.a
,因为对象在JavaScript中是作为引用传递的,这意味着如果你为同一个对象设置了多个变量,它们都是相同的对象;所以exports
和module.exports
是同一个对象。
但是如果您将exports
设置为新的对象,它将不再设置为module.exports
,因此exports
和module.exports
不再是同一个对象。
蕾妮的回答解释得很好。在答案后面加上一个例子:
Node对你的文件做了很多事情,其中最重要的是包装你的文件。内部nodejs源代码"模块。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。此时模块。导出和导出指向相同的引用。
现在,想象你重写了
exports = function () {
console.log('Hello World');
};
console.log(exports);
console.log(module.exports);
输出将是
[Function]
{}
原因是:module。Exports是一个空对象。我们没有设置任何模块。我们设置Exports = function().....在新的greeting .js中。因此,模块。出口是空的。
技术上是导出和模块。导出应该指向相同的引用(这是正确的!!)但是我们在赋值function()....时使用"="导出,这将在内存中创建另一个对象。因此,模块。出口和出口产生不同的结果。当涉及到出口时,我们无法覆盖它。
现在,假设您重新编写(这称为突变)greeting .js(指向Renee answer)为
exports.a = function() {
console.log("Hello");
}
console.log(exports);
console.log(module.exports);
输出将是
{ a: [Function] }
{ a: [Function] }
可以看到模块。Exports和Exports都指向同一个引用,它是一个函数。如果你在exports上设置了一个属性,那么它也会在module上设置。因为在JS中,对象是通过引用传递的。
结论总是使用模块。出口避免混淆。希望这对你有所帮助。快乐编码:)
同样,有一件事可能有助于理解:
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。因为创建了一个新对象。
console.log(this === module.exports); // false
console.log(this === exports); // true
console.log(module.exports === exports); // false
现在,require返回的是模块内部定义的内容。导出,不再是这个或导出。
另一种方法是:
math.js
module.exports.add = function (a, b) {
return a + b;
};
或:
math.js
exports.add = function (a, b) {
return a + b;
};
Rene关于exports
和module.exports
之间关系的回答非常清楚,这都是关于javascript引用的。我想再加一句:
我们在许多节点模块中看到:
var app = exports = module.exports = {};
这将确保即使我们改变了模块。导出,我们仍然可以通过使这两个变量指向同一个对象来使用导出。
节点执行如下操作:
module.exports = exports = {}
模块。
这样做只是为了方便。所以与其写这样的
module.exports.PI = 3.14
我们可以写
exports.PI = 3.14
所以给exports添加一个属性是可以的,但是把它赋值给一个不同的对象是不可以的
exports.add = function(){
.
.
}
↑这是OK的,与module.exports.add = function(){…}相同
exports = function(){
.
.
}
↑this是不允许的,并且将返回一个空对象作为模块。Exports仍然指向{},Exports指向不同的对象
module.exports
和exports
有两个区别
-
当将单个类、变量或函数从一个模块导出到另一个模块时,我们使用
module.exports
。但是将多个变量或函数从一个模块导出到另一个模块,我们使用exports
。 -
module.exports
是从require()调用返回的对象引用。但是exports
不是由require()返回的。
查看示例中的更多细节>>链接
由于上面张贴的所有答案都解释得很好,我想补充一些我今天遇到的问题。
当你使用exports导出一些东西时,你必须使用变量。如,
File1.js
exports.a = 5;
在另一个文件
File2.js
const A = require("./File1.js");
console.log(A.a);
module.exports
File1.js
module.exports.a = 5;
在File2.js const A = require("./File1.js");
console.log(A.a);
和default module.exports
File1.js
module.exports = 5;
在File2.js const A = require("./File2.js");
console.log(A);
myTest.js
module.exports.get = function () {};
exports.put = function () {};
console.log(module.exports)
// output: { get: [Function], put: [Function] }
exports
和module.exports
是相同的,并且是对同一个对象的引用。您可以根据自己的方便通过两种方式添加属性。
您可以将导出视为模块的快捷方式。内的导出给定的模块。实际上,exports只是一个得到的变量初始化为module的值。导出模块评估。该值是一个对象(空对象)的引用这种情况下)。这意味着导出包含对相同内容的引用由module.exports引用的对象。这也意味着通过赋值导出的另一个值不再绑定到module.exports.
这个来自MDN的解释对我来说是最清楚的。
基本上,内存中有一个对象由两个变量- exports和module.exports引用。
exports.a = 23
=
module.exports = {a:23}
,
exports = {a:23}
不等于
module.exports = {a:23}
当你把一个新的对象直接赋值给exports
变量,那么这个变量就不再引用module.exports
了
- 铬:“;未捕获的语法错误:意外的标记:"
- 可以设置“;文件名"发生错误时显示的内联脚本标记的
- JS表单提交"无法使用Chrome数据保护程序加载此页面.尝试重新加载页面.调试信息:POST CISmtuK
- 检测电话窃听,即:<a href="电话:xxx">在UIWebview上
- 使用“+="操作人员
- //而不是在src=“”上使用http://"属性
- "未捕获的语法错误:意外的标记}"
- 可以<脚本类型=“;text/javascript”>window.location=“/"</
- "实例范围”;TypeScript类的getter/setter
- Javascript复选框函数:;缺少:在属性id之后"
- "“;变量未引用正确的对象
- "日期“;AJAX请求返回的类型值未定义
- 为什么要对define.md和module.exports进行条件检查,以及条件何时通过
- 得到"TypeError:无法读取属性'filename'未定义的“;调用“npm start
- Soundcloud api"未捕获的类型错误:无法读取属性'uri'“未定义”;
- "工具提示"jQuery插件坏了
- 在gump和nodejs中使用Typescript时,未定义对require和exports的引用
- "锻造;React中的表达式
- 图像可以从源<img src=""/>.TEXT可以在没有javascript的情况下从外部
- 如何提取“;href"最近列表项中的属性值