module原理

在学习nodejs,首先是看了廖雪峰老师的nodejs教程,因为它比较短,比较容易系统看一遍来入门。

快速的过了一遍,module原理感觉是其中一个重点。

模块化可以解决javascrip全局变量污染的问题,而且模块化也比较符合软件工程的要求。

nodej通过CommonJS规范实现模块化,什么是CommonJS规范后续需要单独学习学习。

nodejs通过module.exports来暴露模块。

通过require来引入模块。

假设我写了个sum.js模块用来计算参数a和参数b的和

function sum(a,b){
    return a+b;
}
module.exports = sum;

当我通过require来引用模块的时候,nodejs把sum.js的代码放到一个load函数中

var module = {
    id: 'hello',
    exports: {}
};
var load = function (exports, module) {
    // sum.js的文件内容开始
    function sum(a,b){
    	return a+b;
    }
    module.exports = sum;
    //sum.js的文件内容结束
    // load函数返回:
    return module.exports;
};

下面是我的猜测了,require函数返回的就是load函数的执行结果,require当然会做很多事,比如加载js文件等,这里就做一个模拟,可能还是错的

function require(moduleName){
    if(moduleName==="sum.js"){
        return load(module.exports,module);
    }
    throw "没有找到模块:"+moduleName;
}

在调用文件中,可以通过require来调用sum.js模块了

var sum = require("sum.js");
var sumResult = sum(1,1);
console.log(sumResult);

所有代码合在一起

var module = {
    id: 'hello',
    exports: {}
};
var load = function (exports, module) {
    // sum.js的文件内容开始
    function sum(a,b){
    	return a+b;
    }
    module.exports = sum;
    //sum.js的文件内容结束
    // load函数返回:
    return module.exports;
};
function require(moduleName){
    if(moduleName==="sum.js"){
        return load(module.exports,module);
    }
    throw "没有找到模块:"+moduleName;
}
var sum = require("sum.js");
var sumResult = sum(1,1);
console.log(sumResult);

其中廖雪峰老师提到

如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;

如果要输出一个函数或数组,必须直接对module.exports对象赋值。

所以我们可以得出结论:直接对module.exports赋值,可以应对任何情况。

这里我卡了好一会,直到验证了这个事实

var a = {};
function test1(a1){
	a1 = {
		b:1
	}
	return a;
}
function test2(a2){
	a2.b = 1;
	return a;
}
console.log(test1(a));//{}
console.log(test2(a));//{b:1}

c语言指针,引用,传值,传址,传引用等基础知识还是能够帮助理解的。

所以

var module = {
    id: 'hello',
    exports: {}
};
var load = function (exports, module) {
    // sum.js的文件内容开始
    function sum(a,b){
    	return a+b;
    }
    //module.exports = sum;
    //注意这里,改成了用exports而不是module.exports
    //形参exports与实参module.exports指向同一个{}
    //通过形参exports给{}中加了sum这个键和函数sum这个值
    //module.exports同样也指向了这个{}
    //所以通过module.exports.sum可以拿到函数sum
    exports.sum = sum;
    //sum.js的文件内容结束
    // load函数返回:
    return module.exports;
};
function require(moduleName){
    if(moduleName==="sum.js"){
        return load(module.exports,module);
    }
    throw "没有找到模块:"+moduleName;
}
//这里要变了
var sum = require("sum.js").sum;
var sumResult = sum(1,1);
console.log(sumResult);

而想像最开始那样直接返回sum函数,通过exports是做不到的

var module = {
    id: 'hello',
    exports: {}
};
var load = function (exports, module) {
    // sum.js的文件内容开始
    function sum(a,b){
    	return a+b;
    }
    //module.exports = sum;
    //形参exports指向了sum函数,但是实参module.exports依然指向{}
    exports = sum;
    //sum.js的文件内容结束
    // load函数返回:
    return module.exports;
};
function require(moduleName){
    if(moduleName==="sum.js"){
        return load(module.exports,module);
    }
    throw "没有找到模块:"+moduleName;
}
var sum = require("sum.js");
var sumResult = sum(1,1);//抛异常:sum不是一个函数
console.log(sumResult);

再来看一遍

如果要输出一个键值对象{},可以利用exports这个已存在的空对象{},并继续在上面添加新的键值;

如果要输出一个函数或数组,必须直接对module.exports对象赋值。

所以我们可以得出结论:直接对module.exports赋值,可以应对任何情况。

嗯,理解了。

可惜暂时在入门阶段,

没有耐心去读源码,

这个加载module的执行过程是通过廖雪峰老师的教程和自己的猜想合成的,

后续看了源码再来修正吧。

posted on 2019-11-14 23:28  iknow的笔记本  阅读(119)  评论(0编辑  收藏  举报

导航