在ES6之前社区定制了一些模块加载方案,例如CommonJS和AMD,前者用于服务器(Node),后者用于浏览器。后来ES6也实现了模块功能,即import/export,ES6可以取代CommonJS和AMD,只是有些引擎还未完全实现ES6,必须借助babel将ES6转化成ES5。
ES6 import/export
// export.js
export const person = {name: "forest"}
// index.js
import { person } from './export'
console.log(person) // {name: "forest"}
export const导出数据,必须添加{}修饰符,而导入的时候也要{}
一个文件可以有多个export const 导出,而只能有一个export default
用export default导出数据,不需要加{}。导入的时候可以自定义对象名字,而且不需要加{}
// export.js
const person = {name: "forest"}
export default person
// index.js
import data from './export.js'
console.log(data) // {name: "forest"}
export default导出的时候也可以加{},可用于多个对象导出
// export.js
const person = {name: "forest"}
const address = {city: "beijing"}
export default {person}
// index.js
import data from './export.js'
console.log(data) // {person: {name: "forest"}}
// 如果导出为 export default {person,address}, 才会有address信息
CommonJs require/module.exports
// export.js
const person = {name: "forest"}
const address = {city: "beijing"}
module.exports = {person,address}
// index.js
const data = require('./export')
console.log(data) // {person: {name: "forest"}, address: {city: "beijing"}}
也可以用exports替代module.exports
// export.js
const person = {name: "forest"}
const address = {city: "beijing"}
exports.person = person
exports.address = address
// index.js
const data = require('./export')
console.log(data) // {person: {name: "forest"}, address: {city: "beijing"}}
区别
ES6模块的设计思想是尽量的静态化,编译时就能确定模块的依赖关系以及输入和输出的变量;CommonJS和AMD模块只能在运行时确定这些东西,CommonJS模块就是对象,输入时必须查找对象属性。
CommonJS模块是运行时加载,ES6模块是编译时输出接口,即require
是异步加载,import
是同步加载
CommonJS加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。而ES6模块不是对象,它的对外接口是一种静态定义,在代码解析阶段就会生成。因为require是运行时加载模块,import命令无法取代require的动态加载功能
以下代码可以看二者区别
// ok
const currentModule = require(process.cwd() + moduleName)
// syntaxError
const currentModule = import(process.cwd() + moduleName)
CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用
CommonJS 模块输出的是值的拷贝,即一旦输出一个值,而模块内部的变化就影响不到这个值。而 ES6 模块的运行机制与 CommonJS 不一样:JS 引擎对脚本静态分析的时候,遇到模块加载命令
import
,就会生成一个只读引用。等到脚本真正执行时,再根据这个只读引用,到被加载的那个模块里面去取值。因此,ES6 模块是动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块。
webpack中的import
webpack中的import是一个方法,返回结果是promise,能够实现懒加载,和这里的import不同。