在用Node.js进行web开发时候,由于要用到各种包,不管是自己写的模块还是install进来的,一般都会用到一个Node.js的包引入关键字module.exports
和require
;但是对其module模块的加载机制其实我不是特别的清楚,只是会用;
只是了解其有缓存机制,一般只要require
完一个模块后,其他地方再require
进来一个模块后会有些不同缓存的结果。如:
|
|
但是对其具体的模块机制没有个整体的认识,今天就着重看看Node.js模块的机制,同时也对比javascript 标准的ES6中包引入机制的差别。
Node.js module机制
Node.js总的加载顺序入下所示:
缓存
Node.js 模块第一次调用require
加载完成后就将其缓存起来,多次require
同一个模块不会使得该模块的代码被多次执行。
如下面代码:
m.js
:
|
|
main.js
:
|
|
运行结果:
由此可知多次require同一个模块,只是取第一次的缓存,并且两者是一致的引用,是一种单例模式
note:exports
和module.exports
其实是同一个对象,但是如果将引入方式写成下面的注意变化
m.js
:
|
|
main.js
:
|
|
运行结果:
循环依赖
在这里会有循环依赖的情况发生,Node.js包机制怎么处理的呢,比如一个a.js
里引入了b.js
,而b.js
里又引入了a.js
,这样就产生了循环依赖的情况,要是我们自己想下,这里该怎么处理呢,比如程序里有
这里主程序会引入a
模块,a
又引入b
模块,但是b
模块代码里又执行引入a
模块的代码,其实这里就是a
模块被引入多次,取第一次load的缓存。其实不会出现循环依赖的死循环
a.js
:
|
|
b.js
:
|
|
main.js
:
|
|
运行结果为:
ES6机制
先熟悉AMD的模块加载方式吧,AMD(Asynchronous Module Definition)采用异步的加载模块,这个很适合在浏览器环境下require([module], callback)
等module
加载完成后会执行callback
回调;
ES6的加载方式就集合了CommonJS
和AMD
两种加载方式:
- 和
CommonJS
相似,都支持单一引入和循环依赖 - 和
AMD
相似,支持异步加载模块,和’configurable module loading’(不懂啥作用)
用法:
|
|
由于ES6机制写入javascript语言里,和上面两者又有些改善:
- 语法较
CommonJS
更紧凑 - 可以静态分析(包括静态检查和优化等)
- 比
CommonJS
更好的支持了循环依赖
ES6 export
import
机制由于是静态的,所以不能在js代码里条件性的引入包,同时包引入会被提升,无论import
写在什么位置都会被提升到当前作用域的最前端。
|
|
若果先引入a.js
的话,调用a.bar()
直接报:Maximum call stack size exceeded
,在引入a.js
完成前,b.js
不能获取a.foo
,但是一旦a.js
加载完成,(ii)就可以执行了;就造成了循环调用的问题。
而ES6的写法:
在ES6 imports
是可以实时显示exported
的值
如代码: