0%

node的深刻认识

node模块的认识

  • node的模块分为核心模块和文件模块,其中,核心模块指的是node本身就有的模块,这部分模块在node的源代码编译中,就已经编译成二进制加载到内存中,只需要路径分析就可以执行了;而文件模块指的是用户自己编写的模块,这些模块需要经过,路径分析,文件定位,编译执行,是在运行时才执行的模块。

  • node的所有模块第一次引入后,都会进行缓存,之后,再引入的时候,就缓存中取;node缓存的是编译,执行后的对象

    node模块的引入方式

  1. 核心模块引入,如: http,fs
  2. 相对路径引入文件模块
  3. 绝对路径引入文件模块
  4. 非路径引入的自定义模块,如: “自定义的connect模块。”

node的模块路径

  • 模块路径是node定位文件的一种查找策略
1
2
// 以数组的形式返回
console.log(module.path)

node的扩展名分析

  • 在用require引入模块时可以不加后缀名,这是node机制会从.js,.json,.node,补足扩展名,依次尝试,而在尝试的过程中会引入fs模块,判断文件是否存在。因为node是单线程,所以会引起性能问题的地方

node对文件的加载编译

  • .js文件。通过fs模块同步读取文件后编译执行。
  • .node文件。这是用C/C++编写的扩展文件,通过dlopen()方法加载最后编译生成的文件。
  • .json文件。通过fs模块同步读取文件后,用JSON.parse()解析返回结果。
  • 其余扩展名文件。它们都被当做.js文件载入。
1
2
// 获得系统中已有的扩展加载方式
console.log(require.extentions)

javascript的编译

  • require,exports,module,filename,dirname的来源
    我们都知道这5个变量在模块中并没有定义,却可以在模块中使用。实质上,在编译过程中,node在获取JavaScript内容时进行了包装,“在头部添加了(function (exports, require, module, __filename, __dirname)”,“{\n,在尾部添加了\n});”

正常编译过后的文件

1
2
3
4
5
6
(function (exports, require, module, __filename, __dirname) {
var math = require('math');
exports.area = function (radius) {
return Math.PI * radius * radius;
};
})
  • 包装后的代码,通过vm原生模块的runInThisContext执行,返回一个function的对象,“最后,将当前模块对象的exports属性、require()方法、module(模块对象自身),以及在文件定位中得到的完整文件路径和文件目录作为参数传递给这个function()执行”

-------------本文结束感谢你的阅读---------