CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
CommonJS
加载的是一个对象(即module.exports
属性),该对象只有在脚本运行完才会生成。而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
CommonJS
模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。ES6
模块的运行机制与 CommonJS
不一样。JS
引擎对脚本静态分析的时候,遇到模块加载命令import
,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。换句话说,ES6
的import
有点像 Unix 系统的“符号连接”,原始值变了,import
加载的值也会跟着变。因此,ES6
模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
1. 直接输出 一个变量(包括函数和class)
// 输出函数
export const sayHi = name => {
alert(`hello,${name}`)
};
// 输出普通变量
export const age = 22;
// 输出一个class(类)
export class Person {
constructor(name,age) {
this.age = age;
this.name = name;
}
sayHi () {
console.log(`hello,this is ${this.name},I am ${this.age} years old.`);
}
}
相应的,引入一个变量
import { age } from './hello.js';
console.log(age); // 22
2. 输出一组变量,用一对花括号把要输出出去的变量都包裹起来。
const sayHi = name => {
alert(`hello,${name}`)
};
const age = 22;
const sex = 'male';
export { sayHi, age, sex };
相应的引入一组变量:
import { sayHi, age, sex } from './hello.js'
console.log(age,sex); // 22 "male"
sayHi('laocao'); // alert "hello,laocao"
或者使用 *
号引入,然后使用一个名字来代表那一组变量,访问变量的方式和对象一样使用.
来访问:
import * as obj from './hello.js'
console.log(obj.age,obj.sex); // 22 "male"
obj.sayHi('laocao'); // alert "hello,laocao"
3. 默认输出
export default class Person {
constructor(name,age) {
this.age = age;
this.name = name;
}
sayHi () {
console.log(`hello,this is ${this.name},I am ${this.age} years old.`);
}
}
相应地,既然你默认输出一个变量,那么我import
就可以随意声明一个变量都会访问到这个默认变量,而且不需要花括号:
import Person from './hello.js'
new Person('laocao', 22).sayHi(); // hello,this is laocao,I am 22 years old.
注意:
1.export命令规定的是对外的接口,必须与模块内部的变量建立一一对应关系。
// 报错
export 1;
// 报错
var m = 1;
export m;
//正确
// 写法一
export var m = 1;
// 写法二
var m = 1;
export {m};
// 写法三
var n = 1;
export {n as m};
2.export命令可以出现在模块的任何位置,只要处于模块顶层就可以。如果处于块级作用域内,就会报错。import同样如此。
function foo() {
export default 'bar' // SyntaxError
}
foo()
【1】阮一峰 ES6入门
【2】知乎