面试题答案
一键面试区别
- 本质:
exports
实际上是module.exports
的一个引用。在Node.js模块的顶层作用域中,Node.js会自动创建一个module
对象,这个对象有一个exports
属性,exports
就是指向module.exports
。module.exports
才是真正决定模块对外暴露内容的对象。
- 赋值操作:
- 对
exports
进行重新赋值,并不会改变module.exports
的指向。例如:
- 对
exports = {
data: 'new value'
};
// 这里的exports重新赋值,不会影响module.exports,外部引用模块时获取不到这个新对象
- 对
module.exports
进行赋值,会直接改变模块对外暴露的内容。例如:
module.exports = {
data: 'new value'
};
// 外部引用模块时,获取到的就是这个新对象
- 添加属性操作:
- 向
exports
添加属性,实际上是向module.exports
添加属性。例如:
- 向
exports.data = 'value';
// 等同于module.exports.data = 'value';
- 向
module.exports
添加属性,直接影响模块对外暴露的内容。例如:
module.exports.data = 'value';
因理解不当导致代码出错的场景
假设我们有一个模块math.js
,代码如下:
// math.js
exports.add = function(a, b) {
return a + b;
};
exports = {
subtract: function(a, b) {
return a - b;
}
};
然后在另一个文件main.js
中引用这个模块:
// main.js
const math = require('./math');
console.log(math.add(2, 3)); // 这里会出错,因为exports重新赋值后,add函数不再属于导出内容
在上述场景中,开发者本意可能是想添加一个subtract
函数并导出,但因为对exports
和module.exports
的区别理解不当,重新赋值exports
导致之前添加的add
函数不再属于模块的导出内容,从而在使用时出错。如果要正确导出两个函数,应该使用module.exports
或者直接在exports
上添加属性,如下:
// 正确方式一:使用module.exports
module.exports = {
add: function(a, b) {
return a + b;
},
subtract: function(a, b) {
return a - b;
}
};
// 正确方式二:使用exports添加属性
exports.add = function(a, b) {
return a + b;
};
exports.subtract = function(a, b) {
return a - b;
};