这些规范的目的都是为了JavaScript的模块化开发,
AMD(Asynchronous Module Definition)[require.js]
特点:实现异步加载依赖模块,并且会提前加载,对于依赖的模块提前执行(依赖前置)。
define(id?, depencies?, factory)
define('add', ['utils'], function(utils){
return utils.add(1,2)
})
CMD(Common Module Definition)[sea.js]
特点:实现异步加载依赖模块,对于依赖的模块就近加载(依赖后置)
define('add', function(require, exports, module){
exports.run = function(){
return 2
}
})
define('minus', function(require, exports, module){
exports.run = function(){ return 3}
})
define('main', function(require, exports, module){
const add = require('add')
a.run()
const minus = require('minus')
minus.run()
})
seaJs.use('main')
CommonJs
特点:运行时加载,同步加载模块,适用于服务端,node.js遵循该规范
- 1、对于基本数据类型引用属于值引用,同时,在另一个模块可以对该模块输出的变量重新赋值
- 2、对于复杂数据类型引用属于地址引用,由于两个模块引用的对象指向同一个内存空间,修改时会影响到另一个模块
- 3、使用require命令加载模块时,会运行整个模块代码
- 4、使用require命令加载同一个模块时,不会在执行该模块,而是提取到缓存之中的值。也就是说,CommonJs无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非主动清除系统缓存。
- 5、循环加载时,属于加载时执行,即脚本代码在require的时候,就会全部执行,一旦出现某个模块被循环加载,就只输出已经执行部分,还未执行的部分不会输出
// b.js
exports.done = false
let a = require('./a.js')
console.log('b.js:1', a.done)
exports.done = true
console.log('b.js:2', 'end')
// a.js
exports.done = false
let b = require('./b.js')
console.log('a.js:1',b.done)
exports.done = true
console.log('a.js:2', 'end')
// c.js
let a = require('a.js')
let b = require('b.js')
console.log('c.js:1', '执行完毕', a.done, b.done)
node c.js
// b.js:1 false
// b.js:2 执行完毕
// a.js:1 true
// a.js:2 执行完毕
// c.js:1 执行完毕 true true
//----------------------------------------------------
遇到require('a.js')的时候,去执行a.js。a.js内只执行了exports.done = false随即遇到requrie('b.js'),去执行b.js。执行b.js时exports.done = false,随即也遇到require('a.js')遇到重复引用的就会提取之前运行的值此时提取到exports.done = false。
-
执行c.js,
- 遇到require('a.js'),此时进入到a.js里执行里面代码,
- a.js
- 定义exports.done = false
- 遇到let b = require('b.js'),此时进入到b.js里执行里面代码
- b.js
- 定义exports.done = false
- 遇到let a = require('a.js')//此时已经加载过一次,直接拿结果,也就是上面定义的exports.done = false,继续执行
- 打印console.log('b.js:1', a.done)
- exports.done = true
- 打印console.log('b.js:2', 'end')
- b.js
- 继续执行a.js
- console.log('a.js:1', b.done)
- exports.done = true
- console.log('a.js:2; 'end')
-
继续执行c.js
- let b = require('b.js') 此时直接拿结果即可exports.done = true
ESModule
## ESModule
* 1、ES6模块中的值属于【动态只读引用】
* 2、对于只读来说,即不允许修改引入变量的值,import的变量是只读,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,在根据这个只读引用,到被加载的那个模块里面去取值。
* 3、对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
* 4、循环加载时,es6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行
```javascript
export const obj = {}
export const add = (a, b) => a+b
import {obj, add} from '...'