Node模块化----CommonJS

Node模块化----CommonJS

1.什么是CommonJS

CommonJS是一个模块化规范

最初是在浏览器之外的地方使用

  • Node是CommonJS在服务端的具体实现
  • Broserify是CommonJS在浏览器的实现
  • webpack页具备对CommonJS支持与转换

2.CommonJS的具体内容

  • 在Node中每一个js文件都是一个单独的模块,即实例module
  • CommonJS规范的核心变量:exports、module.exports、require

3.CommonJS基本语法

obj变量和export变量指向同一块内存。

导出

exports.name = '胡勇'
exports.age = 21

导入方式1

const obj=require("./main")

console.log(obj.name);
console.log(obj.age);

导入方式2

const {name, age} = require('./main')
console.log(name)
console.log(age)

4. module.exports和exports有什么关系或者区别呢

CommonJS并没有module.exports概念,但是Node是Module类实现模块的导出,每一个模块都是一个Module实例,即module。

关系:node会在内部进行初始化,exports=module.exports

区别:导出的时候,实际导出的是module.exports引用的对象。如果exports改变引用的对象,那么exports就没有意义了。

重要:module.exports=exports是在最顶层进行赋值。

​ 下面导出对象为:{},而不是3,即在exports=3之前,module.exports=exports。

exports=3

5.为什么存在exports?

因为CommonJS模块化规范,要求有一个exports作为导出。

6.模块的加载的查找规则

  • 核心模块
    • 直接返回
  • ./ …/ 和**/**开头
    • 如果有后缀名,去对应目录下,按照后缀名格式查找文件
    • 如果没有后缀名 文件名:x
      • 第一步:直接查找x,找不到按照x.js,x.json,x.node查找
      • 第二步:若有对应的x文件夹,在x文件夹下面,查找index.js,index.json,index.node
      • 第三步:如果前面第一步和第二部都没有找到,报错。
  • 直接是一个x路径,并且不是核心模块
    • 去下面路径所在文件夹,查找x.js,x.json,x.node

7.模块的加载过程

  • 模块被引入的过程时候,模块里代码会被执行一遍。

  • 模块被引入一次后,会被缓存到其父模块中。再次引入可以直接父模块获取module.exports引用对象的缓存

  • 模块加载如果设计到多个模块的加载,按照深度优先搜索(DFS Depth first search)顺序加载。

    下图模块加载的顺序为:aaa,ccc,ddd,eee,bbb

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rXsa3JGf-1615690972894)(https://i.loli.net/2021/03/12/xobraBS5eHMcdYF.png)]

8.模块的循环加载过程

CommonJS模块的循环加载,阮一峰的网络日志,写的比较好,这里我直接引用,下面给出连接。

CommonJS模块的重要特性是加载时执行,即脚本代码在require的时候,就会全部执行。CommonJS的做法是,一旦出现某个模块被"循环加载",就只输出已经执行的部分,还未执行的部分不会输出。

让我们来看,官方文档里面的例子。脚本文件a.js代码如下。

exports.done = false;
var b = require('./b.js');
console.log('在 a.js 之中,b.done = %j', b.done);
exports.done = true;
console.log('a.js 执行完毕');

上面代码之中,a.js脚本先输出一个done变量,然后加载另一个脚本文件b.js。注意,此时a.js代码就停在这里,等待b.js执行完毕,再往下执行。

再看b.js的代码。

exports.done = false;
var a = require('./a.js');
console.log('在 b.js 之中,a.done = %j', a.done);
exports.done = true;
console.log('b.js 执行完毕');

上面代码之中,b.js执行到第二行,就会去加载a.js,这时,就发生了"循环加载"。系统会去a.js模块对应对象的exports属性取值,可是因为a.js还没有执行完,从exports属性只能取回已经执行的部分,而不是最后的值。

a.js已经执行的部分,只有一行。

exports.done = false;

因此,对于b.js来说,它从a.js只输入一个变量done,值为false

然后,b.js接着往下执行,等到全部执行完毕,再把执行权交还给a.js。于是,a.js接着往下执行,直到执行完毕。我们写一个脚本main.js,验证这个过程。

var a = require('./a.js');
var b = require('./b.js');
console.log('在 main.js 之中, a.done=%j, b.done=%j', a.done, b.done);

执行main.js,运行结果如下。

$ node main.js

在 b.js 之中,a.done = false
b.js 执行完毕
在 a.js 之中,b.done = true
a.js 执行完毕
在 main.js 之中, a.done=true, b.done=true

上面的代码证明了两件事。一是,在b.js之中,a.js没有执行完毕,只执行了第一行。二是,main.js执行到第二行时,不会再次执行b.js,而是输出缓存的b.js的执行结果,即它的第四行。

exports.done = true;

http://www.ruanyifeng.com/blog/2015/11/circular-dependency.html

9.CommonJS缺点

CommonJS加载模块是同步的,在服务端是本地加载模块,速度比较快。

但是在浏览器,需要将js文件先下载,并且执行完毕,在此之前,后续代码都将不执行,即使是简单的dom操作,因此浏览器可能长时间加载不出来页面,用户体验非常差,不适合于浏览器端。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值