js模块的实现
node中模块的实现,其实是依赖于闭包的,也就是说,module,exports其实都是外部传入的参数,这个简化形式如下:
function NativeModule(id){
this.id=id;
this.filename=id+".js";
this.exports={};
}
NativeModule.require=function(id){
var module=new NativeModule(id);
module.compile();
return module.exports();
};
NativeModule.prototype.compile = function() {
//第一种自执行函数
(
function(exports, require, module, filename, dirname)
{
exports=module.exports=function(){alert(this.id)};
}
(this.exports, NativeModule.require, this, this.filename)
);
//第二种自执行函数
//(
// function(exports, require, module, filename, dirname)
// {
// exports=module.exports=function(){alert(this.id)};
// }
// )(this.exports, NativeModule.require, this, this.filename)
};
NativeModule.require("我是id")
(附:上面的代码可以复制出来直接在控制台运行)
通过上面的代码我们惊奇的发现,其实我们看见的模块文件的代码,一般而言都是类似
exports=module.exports=function(){alert("leexiaosi")};
同时我们也就明白,为什么在模块文件中用var定义的变量都是私有的了。这里关键点就是
NativeModule.prototype.compile
这个函数的实现。为了方便理解,我们设上面的自执行函数
var fnImport=function(exports, require, module, filename, dirname)
那么,根据闭包的原理,这个函数在执行时,其[[scope]]会记录fnImport这个函数定义的作用域的各个变量,
- fnImport函数中的形参值,即this.exports, NativeModule.require, this, this.filename
- fnImport函数中function声明的函数
- fnImport函数中通过var声明的变量
- fnImport函数的父函数的作用域[[scope]]