理解Node.js中的module.exports和exports
引言
作为一个开发者,我们经常遇到的情况是我们需要使用那些我们不熟悉的代码。在这种情况下,我们常常会问自己:我应该花费多少时间来理解这些我需要使用代码?一个典型的答案是:先学到能够上手使用即可,如果接下来时间允许的话再针对各个主题深入研究。
在我学习Node.js的时候,我一度对module.exports
和exports
产生了一些困惑。本文讲得就是我在这个过程中学到的东西。
什么是模块
一个模块会把相关联的代码包裹进一个单独的代码单元中。当我们在编写一个模块时,这可以被解释为将所有先关联的函数放入到一个文件中。
下面我们用一个例子来解释Node.js中的模块。假设我们创建了一个叫做greeting.js
的文件并且其中包含以下两个函数:
`// greetings.js
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};`
输出一个模块
当greeting.js
中的代码可以被其他文件所使用时,它的有用性会大大增加。因此我们来重构greeting.js
来达到这个目标。为了理解实际发生了什么事,我们将全过程分解为下面三个步骤:
假设下面这行代码存在于
greeting.js
的第一行:greetings.js:
// greetings.js var exports = module.exports = {};
将你想要暴露给其他文件的东西都赋值给
exports
对象:// greetings.js // var exports = module.exports = {}; exports.sayHelloInEnglish = function() { return "HELLO"; };
exports.sayHelloInSpanish = function() { return "Hola"; };
在上面的代码中,我们可以用module.exports
来替换exports
来带到同样的目的。如果你感到很困惑,只需要记住exports
和module.exports
是指向同一个对象的引用即可。
这是module.exports的实际值:
module.exports = { sayHelloInEnglish: function() { return "HELLO"; },
sayHelloInSpanish: function() { return "Hola"; } };
引入一个模块
我们现在要将greeting.js
中可用的方法引入到一个叫做main.js
的新文件中。这个过程可以被描述为三个步骤:
Node.js使用
require
关键字来引入模块。假设下面就是require
定义的方式:var require = function(path) { // ... return module.exports; };
假设我们在
min.'s
中require了greeting.js
:// main.js var greetings = require('./greetings.js');
上面的代码等价于:
// main.js
var greetings = {
sayHelloInEnglish: function() {
return "HELLO";
},
sayHelloInSpanish: function() {
return "Hola";
}
};
我们现在可以直接在
main.js
中获取greeting.js
中的可用方法:// main.js // var greetings = require('./greetings.js'); // "Hello" greetings.sayHelloInEnglish();
// "Hola" greetings.sayHelloInSpanish();
凸点
关键字require
会返回一个对象,它引用的是某个给定文件中的module.exports
的值。如果一个开发者有意或者无意将module.exports
二次赋值为一个不同的对象或者数据结构,那么任何添加到原来module.exports
对象中的属性将不可访问。
下面的例子说明了这一点:
// grettings.js
// var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
return "HELLO";
};
exports.sayHelloInSpanish = function() {
return "Hola";
};
// 这一行代码对module.exports进行了二次赋值 module.exports = "Bonjour";
现在我们在min.'s
中require greeting.js
:
var greetings = require('./greetings.js');
到目前为止还没有任何的异常出现,我们可以将greeting变量用于任何需要的地方。
然而,当我们试着调用sayHelloInEnglish
以及sayHelloInSpanish
的时候会发生错误。
// main.js
// var greetings = require('./greetings.js');
// TypeError: object Bonjour has no method 'sayHelloInEnglish'
greetings.sayHelloInEnglish();
// TypeError: object Bonjour has no method 'sayHelloInSpanish'
greetings.sayHelloInSpanish();
为了理解为什么这样的错误会发生,我们将greetings
的值打印在控制台上:
// "Bonjour"
console.log(greetings);
在这里,我们试着在字符串’Bonjour’上调用sayHelloInEnglish
和sayHelloInSpanish
方法。换句话说module.exports
已经不再是原来包含这些方法的默认对象的引用了。
本文译自UNDERSTANDING MODULE.EXPORTS AND EXPORTS IN NODE.JS,原文地址http://www.choskim.me/understanding-module-exports-and-exports-in-node-js/