ES6 - 5分钟看清CommonJS和ES Module
模块化目的
- 解决命名冲突
- 提供复用性
- 提高代码可维护性
ES Module
export
默认导出:
export default Person按需导出:
export { age, name, sex }(推荐)// 导出变量 export const name = "蛙人" export const age = 24 // 导出函数也可以 export function fn() {} export const test = () => {}
// 如果有多个的话
const name = "skinner"
const age = 33
export { name, age }
```混合导出与导入
可以使用
export和export default同时使用并且互不影响,只需要在导入时地方注意,如果文件里有混合导入,则必须先导入默认导出的,在导入单个导入的值。//混合导出 export const name = "skinner" export const age = 33 export default { fn() {}, msg: "hello skinner" }
//混合导入,则该文件内用到混合导入,import语句必须先是默认导出,后面再是单个导出,顺序一定要正确否则报错。
// index,js
export const name = "skinner"
export const age = 24
export default {
msg: "skinner"
}
import msg, { name, age } from './index.js'
console.log(msg)
```- import
默认导入:import Person from "person"
按需导入:
import { age, name, sex } from "person"导入值的变化
export导出的值是值的引用,并且内部有映射关系,这是export关键字的作用。而且导入的值,不能进行修改也就是只读状态。// index.js export let num = 0; export function add() { ++ num } import { num, add } from "./index.js" console.log(num) // 0 add() console.log(num) // 1 num = 10 // 抛出错误Es Module是静态
if (true) { import xxx from 'XXX' // 报错 }
CommonJS
- CommonJS:用于服务器(动态化依赖)
- AMD:用于浏览器(动态化依赖)
- CMD:用于浏览器(动态化依赖)
- ES6 module
CommonJS
注意:浏览器不识别CommonJS语法,因此需要采用browser 打包处理
语法:
module.exports = value | exports.xxx = value
//a.js //方式1: //注意!!:向外暴露的是exports对象,原始exports是{} module.exports = { a: 1 } //方式2 exports.a = 1// b.js var module = require('./a.js') module.a // -> log 1先说b.js中的require,其实就是包装了一层立即执行函数,避免污染全局变量
再说a.js,首先我们需要知道module是怎么实现的,如下。module中有一个特定id,还有一个exports属性
// module 基本实现 var module = { id: 'xxxx', // 我总得知道怎么去找到他吧 exports: {} // exports 就是个空对象 }为什么CommonJS有两个语法,原因如下:
// 这个是为什么 exports 和 module.exports 用法相似的原因 var exports = module.exports
注意:
虽然 exports 和 module.exports 用法相似,但是不能对 exports 直接赋值。因为 var exports = module.exports 这句代码表明了 exports 和 module.exports 享有相同地址,通过改变对象的属性值会对两者都起效,但是如果直接对 exports 赋值就会导致两者不再指向同一个内存地址,修改并不会对 module.exports 起效。再说require执行的是什么函数
//require执行load函数 var load = function (module) { // 导出的东西 var a = 1 module.exports = a return module.exports }; // 然后当我 require 的时候去找到独特的 // id,然后将要使用的东西用立即执行函数包装下
特点
不支持重复导入
let data = require("./index.js") let data = require("./index.js") // 不会在执行了动态导入
CommonJs支持动态导入,什么意思呢,就是可以在语句中,使用require语法,来看如下案例。let lists = ["./index.js", "./config.js"] lists.forEach((url) => require(url)) // 动态导入 if (lists.length) { require(lists[0]) // 动态导入 }导入值是拷贝值
CommonJs导入的值是拷贝的,所以可以修改拷贝值,但这会引起变量污染,一不小心就重名。// index.js let num = 0; module.exports = { num, add() { ++ num } } let { num, add } = require("./index.js") console.log(num) // 0 add() console.log(num) // 0 num = 10上面example中,可以看到
exports导出的值是值的拷贝,更改完++ num值没有发生变化,并且导入的num的值我们也可以进行修改
CommonJs和Es Module的区别
CommonJs
- CommonJs可以动态加载语句,运行时
- CommonJs混合导出,还是一种语法
- CommonJs导出值是拷贝,可以修改导出的值,这在代码出错时,不好排查引起变量污染
Es Module
- Es Module是静态的,不可以动态加载语句,编译时
- Es Module混合导出,单个导出,默认导出,完全互不影响
- Es Module导出是引用值之前都存在映射关系,并且值都是可读的,不能修改
查看3道真题和解析