自己模拟实现exports和module.exports导出功能

2018-02-24  本文已影响10人  yahzon

创建一个foo.js文件,内容如下:
exports.foo = 'bar';
创建index.js文件,内容如下:
// 1. 在Node中,每个文件模块都是一个对象,我们模拟一个

function Module() {
  this.exports = {};
}

// 2. Node在定位到具体的文件后,Node会新建一个模块对象

var module = new Module();

// 3. 如果是.js文件。Node会通过fs模块同步读取文件

var fs = require('fs');
var foo_js = fs.readFileSync('./foo.js');

// 4. 读取出文件内容后,将文件进行头尾包装,这里只是简单的模拟

var packStr = '(function(exports,module){' + foo_js + ' return module.exports; })';

// 注:这样每个模块之间都进行了作用域隔离

// 5. 包装之后的代码通过一个类似eval(Node中并不是eval)的函数执行返回一个具体的function对象

var packObj = eval(packStr);

// 6. 执行该函数,将module对象的exports属性以及module对象本身作为参数传递进去
// 而内部是通过return module.exports; 的方式返回的

var foo = packObj(module.exports, module);

// 在第6点中,就是为什么通过exports = ‘bar’; 赋值,但是外部却拿不到
// 这是因为在JavaScript中,引用传递的是引用的副本,而不是引用本身,这叫做共享传递
// 所以exports = ‘bar’ 改变的是形参的引用()而并没有影响到外部的实参exports对象
// 而通过exports.foo = ‘bar’; 确实可以得到,这是因为虽然引用传递的是引用副本,但他们指向的是同一个对象
// 自然而然的,通过module.exports = ‘bar’; 就是成功的

// 7. 所以在外部我们最终得到了被引用模块中导出的变量、函数或对象

console.log(foo);
上一篇下一篇

猜你喜欢

热点阅读