# 认识CommonJS规范
运行时加载,因为只有运行时才能得到
require
的对象,完全没有办法在编译时进行“静态优化”
CommonJS
中规定每个文件是一个模块。将一个JavaScript文件直接通过script
标签插入页面中与封装成CommonJS
模块最大的不同在于,前者的顶层作用域是全局作用域,在进行变量及函数声明时会污染全局环境;而后者会形成一个属于模块自身的作用域,所有的变量及函数只有自己能访问,对外是不可见的。在
CommonJS
中通过module.exports
可以导出模块中的内容,模块内部会有一个module
对象用于存放当前模块的信息。例子:module.exports = { name: 'calculater', add: function(a, b) { return a + b; } } // 简化书写(不推荐) exports.name = 'calculater'; exports.add = function(a, b) { return a + b; }
1
2
3
4
5
6
7
8
9
10
11在使用
exports
时要注意不要直接给exports
赋值,否则会导致失效:exports = { name: 'calculater' } // 上面的代码由于对exports进行赋值操作,使其指向了新的对象,module.exports却仍然是原来的空对象,因此name属性并不会被导出。
1
2
3
4commonJS
用同步的方式加载模块。在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但是在浏览器端,限于网络原因,更合理的方案是使用异步加载。当我们
require
一个模块时会有两个情况:
require
是Node的语法,浏览器无法识别。运行时加载模块,具有动态加载的功能。
require
模块第一次被加载。这时会首先执行该模块,然后导出内容。require
的模块曾被加载过。这时模块的代码不会再次执行,而是直接导出上次执行后得到的结果。
# CommonJS模块化的特点:
- 加载机制:输入的是被输出的值的拷贝,也就是说:一旦输出一个值,模块内部的变化就影响不到这个值。
- 所有代码都运行在模块作用域,不会污染全局作用域
- 模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。
- 模块加载顺序,按照其在代码中出现的顺序。
同步加载代码,在浏览器会发生堵塞问题,造成页面无响应,所以浏览器不太适合用CommonJS
来加载。
- CommonJS规范对浏览器和服务器端的不同之处:
- 服务器端所有的模块都存放在本地硬盘中,同步加载完成才能执行后续操作,等待时间就是硬盘的读取时间。
- 浏览器,所有的模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于”假死”状态。
TIP
- 每一个文件就是一个模块,拥有自己独立的作用域,变量,以及方法等,对其他的模块都不可见。
CommonJS
规范规定:每个模块内部,module
变量代表当前模块。这个变量是一个对象,它的exports
属性(即module.exports
)是对外的接口。加载某个模块,其实是加载该模块的module.exports
属性。require
方法用于加载模块。 - 模块加载的顺序按照其在代码中出现的顺序
AMD和CMD →