module.exports和exports是nodeJs中的模块导出方式
在一个 node 执行一个文件时,会给这个文件内生成一个 exports 和 module 对象, 而module又有一个 exports 属性。他们都指向一块{}内存区域。
exports = module.exports = {};
具体验证一下
// hello.js
const hello = function () {
console.log('Hello world');
}
console.log('==========');
console.log(exports);
console.log(module.exports);
module.exports = {
hello
}
// 输出结果
初始值==========
{}
{}
可以发现,module对象的exports属性和exports均指向一个空对象{},那么在导出对象的时候使用exports和module.exports有什么区别呢?
我们在使用require()方法引入模块的时候,其实是引入了module.exports对象, exports只是module对象的exports的一个引用,我们可以通过修改exports所指向对象的值来协助修改module.exports的值。
使用exports导出
const hello = function () {
console.log('Hello world');
}
exports.hello = {
hello
}
console.log('==========');
console.log(exports);
console.log(module.exports);
// 输出结果
==========
{ hello: { hello: [Function: hello] } }
{ hello: { hello: [Function: hello] } }
由于exports和module.exports指向同一块内存区域,所以我们修改exports对象的数据,那么module.exports也会随之改变。
用module.exports导出
// hello.js
const hello = function () {
console.log('Hello world');
}
module.exports = {
hello
}
console.log('==========');
console.log(exports);
console.log(module.exports);
// 输出结果
修改值==========
{}
{ hello: [Function: hello] }
会发现修改后的exports依然是{},而module.exports的值已经改变,这是由于给module.exports是直接等于一个新的对象,那么其将指向一块新的内存区域,而此时exports指向的仍然是之前的内存区域,所以二者的值会不一样,但是此时你在其他文件内引入hello.js文件,仍然可以调用hello()方法,这也说明了导出的是module.exports而不是exports。
给exports直接赋值
// hello.js
const hello = function () {
console.log('Hello world');
}
exports = {
hello
}
console.log('修==========');
console.log(exports);
console.log(module.exports);
// 输出结果
修改值==========
{ hello: [Function: hello] }
{}
使用这种方法导出在其他文件调用hello方法即会报错,因为该文件模块导出的对象为空,当然也不可能有hello()方法,这种问题的原因同样是指向的内存区域发生变化所导致的。
总结
1.exports对象是module对象的一个属性,在初始时exports和module.exports是指向同一块内存区域的;
2.不改变exports内存指向的情况下,修改exports的值可以改变module.exports的值;
3.尽量使用module.exports以避免混淆。
export和export default是es6中的模块导出方式
1.export default 在一个模块里只能有一个,但是export可以有多个
// 第一组
export default function crc32() { // 输出
// ...
}
import crc32 from 'crc32'; // 输入
// 第二组
export function crc32() { // 输出
// ...
};
import {crc32} from 'crc32'; // 输入
export default 命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default 命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能唯一对应export default 命令。
2.通过export方式导出,在导入时要加{ },export default则不需要
3.export default 命令的本质是将后面的值,赋给default 变量,所以可以直接将一个值写在export default 之后。export var e1='...' 是合法语句,但是export default var e2='...' 是不合法的
// 正确
export var a = 1;
// 正确
var a = 1;
export default a;
// 错误
export default var a = 1;
// 正确
export default 42;
// 报错
export 42;
|