-
模块化进程:
最开始0=>IIFE(立即调用函数)= >AMD/CMD/CommonJS=>UMD=>ES Module
-
CommonJS
CommonJS是服务端模块规范,Node.js采用了这种规范。
CommonJS的
require语法是同步的,当使用require加载一个模块的时候,必须要等这个模块加载完后,才会执行后面的代码。NodeJS 是服务端,使用require语法加载模块,一般是一个文件,只需要从本地硬盘中读取文件,它的速度是比较快的。但是在浏览器端文件一般存放在服务器或者CDN上,如果使用同步的方式加载一个模块还需要由网络来决定快慢,可能时间会很长,这样浏览器很容易进入“假死状态”。所以异步加载的,比较适合在浏览器端使用。用法:require() module.exports
//a.js
var count = 11;
function counter() {
count++;
}
module.exports = {
count: count,
counter: counter
}
//main.js
var mod = require('./a.js');
mod.count; //1
mod.counter();
mod.count; //1
//a.js
export let count = 11;
export function counter() {
count++;
}
//main.js
import {count,counter} from './a.js';
mod.count; //1
mod.counter();
mod.count; //2
特点:1.require()是同步加载模块 2.运行时加载 3.输出值的拷贝;即一旦输出某个值,模块内部的变化影响不到这个值,外部引用这个值不会变
-
E6S Module
用法:import export
特点:1.import是异步加载模块 2.编译时加载 输出接口 3.输出值的引用,import的时候是个只读引用,等到真正执行时再去模块取值;动态引用
import命令输入的变量都是只读的,不能在加载模块的脚本里更改接口
import {a} from './xxx.js'
a = {}; // Syntax Error : 'a' is read-only;
如果a是一个对象,改写a的属性是被允许的
import {a} from './xxx.js'
a.foo = 'hello'; // 合法操作
-
因为两个模块加载机制的不同,所以在对待循环加载的时候,它们会有不同的表现。CommonJS遇到循环依赖的时候,只会输出已经执行的部分,后续的输出或者变化,是不会影响已经输出的变量。而ES6模块相反,使用
import加载一个变量,变量不会被缓存,真正取值的时候就能取到最终的值; -
关于模块顶层的
this指向问题,在CommonJS顶层,this指向当前模块;而在ES6模块中,this指向undefined; -
关于两个模块互相引用的问题,在ES6模块当中,是支持加载CommonJS模块的。但是反过来,CommonJS并不能
requireES6模块,在NodeJS中,两种模块方案是分开处理的。