JSON

Node.js学习之模块化机制原理详解(2)

字号+ 作者:H5之家 来源:H5之家 2017-02-18 16:03 我要评论( )

现在明白了吧?其实我们在模块中像下面的代码那样,直接给 exports 赋值,会改变当前模块内部的形参 exports 对象的引用,也就是说当前的 exports 已经跟外部的 module.exports 对象没有任何关系了,所以这个改变是

现在明白了吧?其实我们在模块中像下面的代码那样,直接给exports赋值,会改变当前模块内部的形参exports对象的引用,也就是说当前的exports已经跟外部的module.exports对象没有任何关系了,所以这个改变是不会影响到module.exports的。因此,下面的这种方式是没有任何效果的,所有的属性和方法都不会被抛出。

//以下操作都是不起作用的

exports = \'Aphasia\';

exports = function(){

console.log(\'Aphasia\')

}

其实module.exports就是为了解决上述exports直接赋值,会导致抛出不成功的问题而产生的。有了它,我们就可以这样来抛出一个模块了。

//这些操作都是合法的

exports.name = \'Aphasia\';

exports.getName = function(){

console.log(\'Aphasia\')

}//相当于下面的方式module.exports = {

name: \'Aphasia\',

getName: function(){

console.log(\'Aphasia\')

}

}

这样就不用每次把要抛出的对象或方法赋值给exports的属性了 ,直接采用对象字面量的方式更加方便。

模块实例的require方法

我们都知道,当使用exports或者module.exports抛出一个模块,通过给require()方法传入模块标识符参数,然后node根据一定的规则引入该模块之后,我们就能使用模块中定义的方法和属性了。这里要讲的就是node的模块引入规则。

1node中引入模块的机制

Node中引入模块,需要经历3个步骤

1)路径分析

2)文件定位

3)编译执行

Node中,模块一般分为两种

1Node提供的模块,例如httpfs等,称为 核心模块 。核心模块在node源代码编译的过程中就编译进了二进制执行文件,在Node进程启动的时候,部分核心模块就直接加载进内存中了,因此这部分模块是不用经历上述的(2)(3)两个步骤的,而且在路径分析中是优先判断的,因此加载速度最快。

2)用户自己编写的模块,称为 文件模块 。文件模块是按需加载的,需要经历上述的三个步骤,速度较慢。

优先从缓存中加载

与浏览器会缓存静态脚本文件以提高页面性能一样,Node对引入过的模块也会进行缓存。不同的地方是,node缓存的是编译执行之后的对象而不是静态文件。这一点我们可以用下面的方式来验证。

modA.js

console.log(\'模块modA开始加载...\')

exports = function() {

console.log(\'Hi\')

}console.log(\'模块modA加载完毕\')

init.js

var mod1 = require(\'./modA\')var mod2 = require(\'./modA\')console.log(mod1 === mod2)

执行 node init.js ,运行结果:


虽然我们两次引入modA这个模块,但是模块中的代码其实只执行了一遍。并且mod1mod2指向了同一个模块对象。

下面是Module._load的源码:

Module._load = function(request, parent, isMain) {

// 计算绝对路径

var filename = Module._resolveFilename(request, parent);

// 第一步:如果有缓存,取出缓存

var cachedModule = Module._cache[filename];

if (cachedModule) {

return cachedModule.exports;

// 第二步:是否为内置模块

if (NativeModule.exists(filename)) {

return NativeModule.require(filename);

}

// 第三步:生成模块实例,存入缓存

var module = new Module(filename, parent);

Module._cache[filename] = module;

// 第四步:加载模块

try {

module.load(filename);

hadException = false;

finally {

if (hadException) {

delete Module._cache[filename];

}

}

// 第五步:输出模块的exports属性

return module.exports;

};

对应流程如下图所示:

2、路径分析和文件定位

路径分析

模块标识符分析:

1)核心模块,如httpfspath

2)以 .  .. 开始的相对路径文件模块

3)以 / 开始的绝对路径文件模块

4)非路径形式的文件模块

1)核心模块:优先级仅次于缓存,加载速度最快;如果自定义模块与核心模块名称相同,加载是不会成功的。若想加载成功,必须选择一个不同的名称或者换用路径。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • JSON学习之完全手册图文

    JSON学习之完全手册图文

    2017-01-12 18:01

  • golang学习之html json解析

    golang学习之html json解析

    2016-10-30 12:00

  • Unity3D学习之使用 C#合成解析XML与JSON.doc.doc

    Unity3D学习之使用 C#合成解析XML与JSON.doc.doc

    2016-06-11 12:00

  • json学习之三:JSONArray的应用

    json学习之三:JSONArray的应用

    2016-01-30 12:32

网友点评