关于underscore源码的一点小疑问

在源码中有这样一段:

if (typeof exports !== 'undefined') {
    if (typeof module !== 'undefined' && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _; // 要么是exports._ = _,要么是module.exports = _
} else {
  root._ = _;
}

我的疑问是exports和module.exports任意用一个就行了,这两个不会有循环引用的问题么?

underscore

阅读 2.8k
2 个回答

module.exportsexports的用途是不一样的,具体表现为如果输出的对象是一个整体对象我们使用module.exports,如果是对象中的属性单个导出则使用exports

// 整体导出
module.exports = {name:'wason',age:24,sex:'male'};
//单个导出
exports.name = 'wason';
exports.age = 24;
exports.sex = 'male';

在初始化的时候, exports 和 module.exports指向的是同一个object, 所以如果你: console.log(module.exports === exports); 会输出 true.

require 导入时, 或者说module导出时, 导出的是module.exports所指向的object, 所以会出现一下情况:

// a.js
exports = "a";

// b.js
var a = require("./a"); // {} -> 因为module.exports依然指向{}
// 或者你只改变了exports的reference, 但没有修改module.exports的话, 也会导致一样的问题, 这也是为什么通常不用exports做整体导出的原因~ 因为最终导出的其实是module.exports所指向的.

所以如果更改为:

// a.js
module.exports = "a";

// b.js
var a = require("./a"); // "a"

但是如果两者始终指向同一个object, 那么如何assign都没有关系的, 比如:

// a.js
module.exports.a = "A";
exports.b = "B";

// b.js
var a = require("./a");
a.a === "A";
a.b === "B";

所以通常会一同使用module.exports, exports, 来确保它们指向同一个object, 这样在之后的使用中也会比较一致, 且exports可以作为module.exports的一个shortcut来使用~

其实为了防止module, exports因为element id的原因而出现误判, 所以这部分代码已经更新为:

  if (typeof exports != 'undefined' && !exports.nodeType) {
    if (typeof module != 'undefined' && !module.nodeType && module.exports) {
      exports = module.exports = _;
    }
    exports._ = _; // 主要是为了老node版本的module语法支持
  } else {
    root._ = _;
  }
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题