module.exports、exports、require、export、import的关系

ES6标准发布后,module成为标准,标准的使用是以export指令导出接口,以import引入模块,但是在我们一贯的node模块中,我们采用的是CommonJS规范,使用require引入模块,使用module.exports导出接口。

module.exports

Node内部提供一个Module构建函数。所有模块都是Module的实例。每个模块内部,都有一个module对象,代表当前模块。它有以下属性。

  • module.id 模块的识别符,通常是带有绝对路径的模块文件名。
  • module.filename 模块的文件名,带有绝对路径。
  • module.loaded 返回一个布尔值,表示模块是否已经完成加载。
  • module.parent 返回一个对象,表示调用该模块的模块。
  • module.children 返回一个数组,表示该模块要用到的其他模块。
  • module.exports 表示模块对外输出的值。

module.exports属性表示当前模块对外输出的接口,其他文件加载该模块,实际上就是读取module.exports变量。 使用module.exports可以将文件中的某个模块(函数或是变量)暴露出去让外部调用

//example.js
var x = 5;
var fn = function (value) {
    return value + x;
};
global.warning = true;

module.exports = fn;

//index.js
var mod = require('./example.js');

// global
console.log(warning);    //interesting
console.log(global.warning);    //interesting
console.log(global.x);    //undefined

// module.exports
console.log(mod(10));   //15

exports

Node为每个模块提供一个exports变量,指向module.exports。 相当于var exports = module.exports;

//index.js
var exp=require('./exports');
console.log(exp.area(5));   //78.53981633974483

//export.js
exports.area = function (r) {
    return Math.PI * r * r;
};

module.exports与exports坑点

//index.js
console.log(mod.area);  //undefined
console.log(mod(10));   //15

//example.js
var x = 5;
var fn = function (value) {
    return value + x;
};

module.exports = fn;

exports.area = function (r) {
    return Math.PI * r * r;
};

由以上运行结果可得出结论:

  • module.exports的值会覆盖exports的值
  • 不要给exports直接赋值。只使用exports时,先给exports赋值会导致引入的值为空
//example.js
exports = {name:Tom};
exports.area = function (r) {
    return Math.PI * r * r;
};

//index.js
var mod = require('./example.js');
console.log(mod);   //{}

只使用exports时,先给exports添加属性或方法再给exports赋值会导致赋值无法存储

//example.js
exports.area = function (r) {
    return Math.PI * r * r;
};
exports = {name:Tom};

//index.js
var mod = require('./example.js');
console.log(mod);   //{ area: [Function] }
console.log(mod.area(10));   //314.1592653589793

通俗点讲,exports先赋值为某个固定值,再添加属性会导致引用结果为空;exports先添加属性,再赋值为某个固定值结果为添加的属性对象。

使用建议 不要混用exports与module.exports 如果你觉得,exports与module.exports之间的区别很难分清,一个简单的处理方法,就是放弃使用exports,只使用module.exports。

nodejs
JSRUN前端笔记, 是针对前端工程师开放的一个笔记分享平台,是前端工程师记录重点、分享经验的一个笔记本。JSRUN前端采用的 MarkDown 语法 (极客专用语法), 这里只属于前端工程师。