Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Node.js 中 module.exports 和 exports 的区别 #17

Open
zwhu opened this issue Dec 16, 2015 · 0 comments
Open

Node.js 中 module.exports 和 exports 的区别 #17

zwhu opened this issue Dec 16, 2015 · 0 comments

Comments

@zwhu
Copy link
Owner

zwhu commented Dec 16, 2015

Node.js中最常用的恐怕就是 require, exports 以及 module.exports 了,那么 exports 和 module.exports 这两者有什么区别,在什么情况下使用 exports,又在什么时候使用 module.exports。

先举个官网的例子:

// circle.js
var PI = Math.PI;

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

exports.circumference = function (r) {
  return 2 * PI * r;
};

在 circle.js 中写的源字符串是上面贴出的代码,然而实际 Node.js 在加载的时候会在原字符串上外面拼出一个闭包,拼出之后的代码如下(有想了解为什么会拼出这个代码的朋友,请看我之前一篇文章):

(function(exports, require, module, __dirname, __filename) {
    // circle.js
    var PI = Math.PI;

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

    exports.circumference = function (r) {
      return 2 * PI * r;
    };
})

Node.js 调用这段代码的为:

function Module(id, parent) {
  this.id = id;
  this.exports = {};
  this.parent = parent;
  if (parent && parent.children) {
    parent.children.push(this);
  }

  this.filename = null;
  this.loaded = false;
  this.children = [];
}


Module.prototype._compile = function(content, filename) {
  var self = this;

  function require(path) {
    return self.require(path);
  }

  var dirname = path.dirname(filename);

  var args = [self.exports, require, self, filename, dirname];
  return compiledWrapper.apply(self.exports, args);
};

从上面这段代码可以看到 exports 是 module 的一个属性,exports 值为 {}。在拼接之后的代码中,给这个函数传入的 exports 是 module.exports, 也就是说 exports 和 modules.exports 引用的是同一个对象。如果我们给 exports 增加属性,那么因为 modules.exports 也会增加相同的属性,此时 modules.exports === exports。然而如果对 exports 赋值的话,那么就会造成 modules.exports 和 exports 不指向同一个对象,此时再对 exports 做任何动作都跟 modules.exports 没有任何关系了,用一段代码模拟就是:

var module = { exports: {}};
var exports = module.exports;
exports.a = 1;
console.log(module.exports); // {a: 1}

exports = {b:2};
console.log(module.exports); // {a: 1}

所以从上面的代码可以看出,如果我们想在模块文件中提供其他模块可以访问的接口,最好写成
exports["key"] = value 或者 module.exports = {key: value} 的形式。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant