理解Node.js中的module.exports和exports
发布在每天学点javascript2014年6月2日view:8789
在文章任何区域双击击即可给文章添加【评注】!浮到评注点上可以查看详情。

enter image description here

理解Node.js中的module.exports和exports

引言

作为一个开发者,我们经常遇到的情况是我们需要使用那些我们不熟悉的代码。在这种情况下,我们常常会问自己:我应该花费多少时间来理解这些我需要使用代码?一个典型的答案是:先学到能够上手使用即可,如果接下来时间允许的话再针对各个主题深入研究。

在我学习Node.js的时候,我一度对module.exportsexports产生了一些困惑。本文讲得就是我在这个过程中学到的东西。

什么是模块

一个模块会把相关联的代码包裹进一个单独的代码单元中。当我们在编写一个模块时,这可以被解释为将所有先关联的函数放入到一个文件中。

下面我们用一个例子来解释Node.js中的模块。假设我们创建了一个叫做greeting.js的文件并且其中包含以下两个函数:

`// greetings.js
sayHelloInEnglish = function() {
  return "Hello";
};

sayHelloInSpanish = function() {
  return "Hola";
};`  

输出一个模块

greeting.js中的代码可以被其他文件所使用时,它的有用性会大大增加。因此我们来重构greeting.js来达到这个目标。为了理解实际发生了什么事,我们将全过程分解为下面三个步骤:

  1. 假设下面这行代码存在于greeting.js的第一行:

    greetings.js:

    // greetings.js var exports = module.exports = {};

  2. 将你想要暴露给其他文件的东西都赋值给exports对象:

    // greetings.js // var exports = module.exports = {}; exports.sayHelloInEnglish = function() { return "HELLO"; };

    exports.sayHelloInSpanish = function() { return "Hola"; };

在上面的代码中,我们可以用module.exports来替换exports来带到同样的目的。如果你感到很困惑,只需要记住exportsmodule.exports是指向同一个对象的引用即可。

  1. 这是module.exports的实际值:

    module.exports = { sayHelloInEnglish: function() { return "HELLO"; },

    sayHelloInSpanish: function() { return "Hola"; } };

引入一个模块

我们现在要将greeting.js中可用的方法引入到一个叫做main.js的新文件中。这个过程可以被描述为三个步骤:

  1. Node.js使用require关键字来引入模块。假设下面就是require定义的方式:

    var require = function(path) { // ... return module.exports; };

  2. 假设我们在min.'s中require了greeting.js:

    // main.js var greetings = require('./greetings.js');

上面的代码等价于:

// main.js

var greetings = {
  sayHelloInEnglish: function() {
    return "HELLO";
  },


  sayHelloInSpanish: function() {
    return "Hola";
  }
};
  1. 我们现在可以直接在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’上调用sayHelloInEnglishsayHelloInSpanish方法。换句话说module.exports已经不再是原来包含这些方法的默认对象的引用了。


本文译自UNDERSTANDING MODULE.EXPORTS AND EXPORTS IN NODE.JS,原文地址http://www.choskim.me/understanding-module-exports-and-exports-in-node-js/

评论
发表评论
4年前

我以为会分析exports,model,require的实现原理呢

WRITTEN BY
张小俊128
Intern in Baidu mobile search department。认真工作,努力钻研,期待未来更多可能。
TA的新浪微博
PUBLISHED IN
每天学点javascript

javascript进阶级教程,循序渐进掌握javascript

我的收藏