module.exports和export

62 阅读2分钟

在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不同。