CMD&AMD
在ES6之前,社区已经有了一些模块化方法,最主要的是用于Node端的CMD和用于浏览器端的AMD。
CMD
在CMD中,有一个全局性方法require(),用于加载模块。假定有一个数学模块math.js,就可以像下面这样加载。
var math = require('math');
math.add(2,3); // 5AMD
AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:require([module], callback);
第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:
require(['math'], function (math) {
math.add(2, 3);
});导出
返回一个JSON
//app.js
var app = {
name:'app'
sayName:function(name){
console.log(this.name)
}
}
module.exports = app
//使用
var app = require('./app.js');
app.sayName('hello');//helloexports.xxx
//functions.js
var func1 = function() {
console.log("func1");
};
var func2 = function() {
console.log("func2");
};
exports.function1 = func1;
exports.function2 = func2;
//使用
var functions = require("./functions");
functions.function1();
functions.function2();两者的区别
CMD 推崇依赖就近,AMD 推崇依赖前置。看代码:
// CMD
define(function(require, exports, module) {
var a = require('./a')
a.doSomething()
// 此处略去 100 行
var b = require('./b') // 依赖可以就近书写
b.doSomething()
// ...
})
// AMD 默认推荐的是
define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好
a.doSomething()
// 此处略去 100 行
b.doSomething()
...
})import&export
import
import命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。
// ES6模块
import { stat, exists, readFile } from 'fs';export
如果你希望外部能够读取模块内部的某个变量,就必须使用export关键字输出该变量。
// profile.js
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
//or
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export { firstName, lastName, year };export default
为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。
// export-default.js
export default function () {
console.log('foo');
}上面代码是一个模块文件export-default.js,它的默认输出是一个函数。其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。
// import-default.js import customName from './export-default'; customName(); //
ES6模块与CommonJS模块的差异
- CommonJS模块输出的是一个值的拷贝,ES6模块输出的是值的引用
- CommonJS模块是运行时加载,ES6模块是编译时输出接口
第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
CommomJS
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值
// lib.js
var counter = 3;
function incCounter() {
counter++;
}
module.exports = {
counter: counter,
incCounter: incCounter,
};
// main.js
var mod = require('./lib');
console.log(mod.counter); // 3
mod.incCounter();
console.log(mod.counter); // 3ES6模块
ES6 的import有点像 Unix 系统的“符号连接”,原始值变了,import加载的值也会跟着变。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}
// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4
京公网安备 11010502036488号