a.js和b.js互相require怎么执行? —— CommonJS模块探究

a.js和b.js互相require怎么执行? —— CommonJS模块探究

学习Node.js遇到2个模块互相引用的问题,有点搞不清楚。我以为这个模块机制对于学习Node.js来讲,搞清代码执行顺序来讲,十分有必要。html

因此在读了相关资料,并实践以后,愉快的在这分享一下成果。node

CommonJS中模块的"循环引用"问题

先说结论: CommonJS中的作法时,一旦某个模块被”循环引用“,也就是这个模块没有加载完,就进入了循环,因此原则是, 只exports已经执行的那部分,没执行的不输出。

若是没看懂,不要紧。我第一遍也没明白。可是看下这个例子就好理解啦~缓存

a.js
module.exports.done = false
var b = require('./a.js')
console.log(`在a模块中,b.done=${b.done}`)
module.exports.done = true
console.log('a模块执行完毕')
b.js
module.exports.done = false
var b = require('./a.js')
console.log(`在a模块中,b.done=${b.done}`)
module.exports.done = true
console.log('a模块执行完毕')

在终端执行模块化

node a.js

下面咱们梳理代码的执行过程。而后本身运行代码验证一下就好啦~学习

  • 1.a模块第1行导出done = false;
  • 2.第2行require('./b.js'),因而a模块暂停,进入并执行b模块
  • 3.b模块第1行导出done = false,以后require('./a.js'),此时出现"死循环",关键是CommonJS会如何处理呢? 请看上面的结论,这里的a模块还没执行完,仅仅执行了一句module.exports.done = false,因此就导出的就是这个。
  • 4.以后b模块执行完后,跳回到a模块第3行,而后依次打印。
终端的结果

clipboard.png

因此问题的关键,就是弄清楚,当a模块还没执行完成时,b模块里require a模块的话,执会导出a模块已经执行完成的部分。ui

上面的例子中,a模块只执行了spa

module.exports.done = false

因此就导出了这个。code

那么建议同窗们,试一下把require('./b.js')放到第一行,试试看执行结果会有什么不一样?htm

若是有同窗实践后,仍是不理解的话,能够看看参考资料里阮一峰老师的文章,或者看一眼我这篇文章的第二个部分,也许缺乏一些CommonJS的其余知识。对象

CommonJS中须要知道的一些知识点

  • 知识点1:require('./a.js')时,不单单是引用方法,若是是第一个require的话,就直接执行a.js了
  • 知识点2:再次require('./a.js')并不会有反复执行a.js的BUG,而是直接从缓存中取值。

被缓存的模块,能够经过require.cache里看到

  • 知识点3:module.exports和exports的区别
// 简单说,require只认module.exports,
// 而初始化时 exports是module.exports的引用

exports = module.exports
  • 知识点4:CommonJS里发生"循环引用"的话,就exports已经执行的部分。ES6发生"循环引用"的话,每次import只生成一个模块引用,不影响使用变量
关于CommonJS里"循环引用"的解决方法
    + 办法1:module.exports = () => {const moduleDemo = require('./b.js')} 避免require时直接执行,使其延迟执行。
    + 办法2:把module.exports提到第一行,但不是万能的,由于要导出的东西可能依赖文件下面的计算

CommonJS与ES6模块中的"循环引用"的区别

每个模块化方案,均可能会遇到"循环引用"的状况,可是执行方式不同。

由于AMD和CMD规范未来会被淘汰,因此ES6和CommonJS更值得拿出来研究一下。

ES6的引入命令是import,例如

import {foo} from './some.js'

ES6引入foo时,不会执行./some.js,而是生成一个该模块的引用,当须要用foo变量时,在到some模块里取值。

因此ES6是动态引用,不会缓存some.js,而是生成一个引用对象。

在import时不去加载。天然地,所谓"循环引用"也就不是问题了。

参考资料
http://www.ruanyifeng.com/blo...

相关文章
相关标签/搜索