commonJS
因为在网页端即使没有模块化,JavaScript也可以工作下去,只是逻辑更加复杂。但在服务端一定要有模块,所以JavaScript第一个流行起来的模块化标准是服务端应用带来的。nodeJS采用了commonJS模块规范。
语法
暴露模块:module.exports = value 或 module.xxx = value
导入模块:require(xxx)
var a = 7
var add = (value) => { reruen valeu + a}
//输出
module.exports.a = a
module.exports.add = add
//输入
const example = require('./module.js')
console.log(example.a, example.add(4)) // 5 11
特点
所有的代码都运行在模块的作用域,不会污染全局函数。
模块加载的顺序是按照代码出现的顺序。
模块输入的是输出的值拷贝。也就是说一旦输出值,模块内部的变化就影响不到这个值了。
AMD 与 CMD
由于commonJS规范模块加载时同步的。只有加载完成才能执行后面的操作。在服务端很简单很自然,然而在浏览器端脚本标签时异步加载,commonJS在浏览器环境中无法正常加载。解决思路有需要在服务端对代码做静态分析,将模块与其他依赖一起返回给浏览器端,这种方法最大缺点就是需要在服务端安装额外组件。另外一种解决思路在另外弄一套模块标准来封装模块定义。
AMD
语法
//定义
define('module', ['dep1', 'dep2'], function(d1, d2){ ... })
//加载
require(['module', './app'] callback()) //数组里面是要加载的模块, 第二个参数是加载成功的回调的函数。
特点
由于JavaScript原生不支持AMD, 因此使用AMD规范需要引入RequireJS
requireJS 首先检查依赖模块,根据配置文件,获取js文件实际的地址。
根据js文件实际路径,在DOM中插入script标签,并且绑定onload事件获取模块加载完通知。
当script全部调用完,调用回调函数。
CMD
语法
特点
ES6 模块化
语法
//暴露模块
export var a = 7
export const add = (vallue) => { return value + a }
export default { }
//引用模块
import { a, add } from './app'
console.log(a, add(1))
特点
ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。
ES6 模块设计思想:尽量的静态化、使得编译时就能确定模块的依赖关系,以及输入和输出的变量(CommonJS和AMD模块,都只能在运行时确定这些东西)。
ES6 与 commonJS 区别
ccommonJS
对于基本数据类型,属于复制。即会被模块缓存。同时,在另一个模块可以对该模块输出的变量重新赋值。
对于复杂数据类型,属于浅拷贝。由于两个模块引用的对象指向同一个内存空间,因此对该模块的值做修改时会影响另一个模块。
当使用require命令加载某个模块时,就会运行整个模块的代码。
当使用require命令加载同一个模块时,不会再执行该模块,而是取到缓存之中的值。也就是说,CommonJS模块无论加载多少次,都只会在第一次加载时运行一次,以后再加载,就返回第一次运行的结果,除非手动清除系统缓存。
循环加载时,属于加载时执行。即脚本代码在require的时候,就会全部执行。一旦出现某个模块被”循环加载”,就只输出已经执行的部分,还未执行的部分不会输出。
ES6 模块
ES6模块中的值属于【动态只读引用】。
对于只读来说,即不允许修改引入变量的值,import的变量是只读的,不论是基本数据类型还是复杂数据类型。当模块遇到import命令时,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。
对于动态来说,原始值发生变化,import加载的值也会发生变化。不论是基本数据类型还是复杂数据类型。
循环加载时,ES6模块是动态引用。只要两个模块之间存在某个引用,代码就能够执行。
commonJS
因为在网页端即使没有模块化,JavaScript也可以工作下去,只是逻辑更加复杂。但在服务端一定要有模块,所以JavaScript第一个流行起来的模块化标准是服务端应用带来的。nodeJS采用了commonJS模块规范。
语法
暴露模块:module.exports = value