To illustrate the behavior, imagine this hypothetical implementation of require(), which is quite similar to what is actually done by require():
function require(/* ... */) {
const module = { exports: {} };
((module, exports) => {
// Module code here. In this example, define a function.
function someFunc() {}
exports = someFunc;
// At this point, exports is no longer a shortcut to module.exports, and
// this module will still export an empty default object.
module.exports = someFunc;
// At this point, the module will now export someFunc, instead of the
// default object.
})(module, module.exports);
return module.exports;
}
一、CommonJS 模块规范
Node 应用由模块组成,采用 CommonJS 模块规范。 每个文件就是一个模块,有自己的作用域。在一个文件里面定义的变量、函数、类,都是私有的,对其他文件不可见。
CommonJS 规范规定,每个模块内部,
module
变量代表当前模块。这个变量是一个对象,它的exports
属性(即module.exports
)是对外的接口。加载某个模块,其实是加载该模块的module.exports
属性。CommonJS 规范加载模块是同步的,也就是说,只有加载完成,才能执行后面的操作。
1. module.exports 属性
module.exports
属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports
变量。2. exports 变量
为了方便,Node 为每个模块提供一个
exports
变量,它指向module.exports
。这等同于在每个模块头部,有一行这样的命令:var exports = module.exports
,我们可以通过以下方式来验证所以在对外输出模块接口时,可以向
exports
对象添加属性方法。但是不能直接将
exports
变量指向一个值,因为这样等于切断了exports
与module.exports
的联系。3. module.exports 与 exports 的使用
当一个模块的对外接口,只是一个单一的值时,不能使用
exports
输出,只能使用module.exports
输出。导入模块看结果:
分析结果: 首先我们要知道
module.exports
的初始值是{}
,当执行exports = function() {};
赋值时,无论赋值的是基本数据类型还是引用数据类型,都将改变exports
的指向,即切断了exports
与module.exports
的联系。但是我们模块对外输出的接口是module.exports
,所以 2️⃣ 得到的是初始值{}
。如果你觉得
exports
与module.exports
之间的区别很难分清,一个简单的处理方法,就是放弃使用exports
,只使用module.exports
。*我个人也没觉得
exports
的写法有多方便,哈哈。4. 总结
非常简单,就三点:
module.exports
初始值为一个空对象{}
;exports
是指向的module.exports
的引用;require()
返回的是module.exports
而不是exports
。还是那句话,如果你觉得
exports
与module.exports
之间的区别很难分清,一个简单的处理方法,就是放弃使用exports
,只使用module.exports
。二、require() 扩展话题
以下案例源自知乎某帖回答,这里。
关于
require()
的解释注意实现顺序,也就是下面代码为什么不成功的原因。
require()
的时候,是先通过exports.abc
获取, 然后通过module.exports
直接覆盖了原有的exports
,所以exports.abc = 'abc'
就无效了。一般库的封装都是
exports = module.exports = _
(underscore 的例子)。原因很简单,通过
exports = module.exports
让exports
重新指向module.exports
。三、References
The end.