# 模块化
详情参阅我的CSDN和阮一峰-Module
# 常用写法
exportfile.js:
//导出变量
export var firstName = "wang";
export var lastName = "long kai";
//导出函数
export function sayHello(name){
console.log(`hello ${name}`);
}
//导出对象
var address = "beijing";
var age = 24;
var sayAddress = function(address){
console.log(`address ${address}`);
}
export {address,age,sayAddress};
//默认导出(一个模块只能有一个默认导出)
export default 42;
importfile.js:
//import 默认导出,{非默认导出...} from 'someWhere.js'
import deafultNum,{firstName,lastName,sayHello,address,age,sayAddress} from './exportfile.js' //可用解构赋值
# export的注意点
1. export语句输出的接口与其对应的值是动态绑定关系,即通过该接口获取到的是模块内部实时的值。
export var foo = "bar";
setTimeout(()=>foo="wlk",500);
上面代码输出的接口(变量)是foo,值为bar。但是,500ms之后值变为wlk。引入该接口的模块中的值也会相应改变。
2. export语句可以出现在模块的任何位置,前提是处于模块的顶层作用域。
function foo(){
export var wlk = "bar";
}
上面的代码会报错,export只能在模块的顶层作用域,而此处位于函数作用域中。
# import的注意点
1. 从其他模块导入的变量是只读的,不能进行修改。
//lib.js
export let obj = {name:"wlk"};
//main.js
import {obj} from "lib.js";
obj.age = 22;//可以
obj.name = "hq";//不可以
上面代码中,main.js从lib.js输入对象obj,可以对obj添加属性,但是不能重新赋值。
2. import命令具有提升效果,会提升到整个模块的头部并首先执行。
foo();
import {foo} from "test.js";
上面代码不会出错,因为import的执行早于foo的调用。这种行为的本质是,import命令是编译阶段执行的,在代码执行之前。
3. 如果多次使用同一import语句,那么只会执行一次,而不会执行多次。
import {foo} from "test.js";
import {foo} from "test.js";
其实只相当于执行语句一次。
# 其他模块化方案
- CommonJS规范
CommonJS规范用于服务器端,nodejs就是使用的Commonjs规范。一个js文件就是一个js模块,模块只有一个出口,即
module.exports对象,我们需要把模块希望输出的内容放入该对象。通过require方法,加载一个模块,是运行时加载。而ES6的模块化方案是静态加载。 - AMD和CMD规范
AMD和CMD规范适用于浏览器端。require.js就是AMD规范,sea.js就是CMD规范。
两者的区别是:
AMD推崇依赖前置,在定义模块时就引入其依赖的模块。
CMD推崇就近依赖,只用在用到某个模块的时候再去require。
二者的执行机制也不一样:二者都是异步加载模块的。
AMD是加载完模块后立即执行模块,所有模块加载和执行完毕后就进入require的回调函数,执行主逻辑。
CMD是加载完某个依赖后并不执行,在所有依赖模块加载完毕后,进入主逻辑,遇到require语句的时候,就执行相应的模块。