文章目录
前言
js
早期没有模块体系,都是通过script
标签引入js
代码,当项目越来越大时,会出现一些问题,比如:
- 变量污染,因为js都是顶层作用域
- 当js文件相互依赖时,问题会更复杂,引入顺序出错时,会报很多错
为了解决以上问题,就出现了模块化,nodejs
使用commonJs
模块化规范;es6
使用Es Module
模块化规范。
CommonJs 用法
导出
可以通过
module.exports
进行单个导出,多个导出,或者混合导出
common.js 文件
// 单个导出
let a = 1
module.exports.a = a
// 多个导出
let a = 1
let b = 2
function add(val1,val2){
a = val1
b = val2
return a+b
}
module.exports ={
a, b, add
}
// 混合导出
let a = 1
let b = 2
function add(val1,val2){
a = val1
b = val2
return a+b
}
module.exports ={
b, add
}
module.exports.a = a
导出也可以直接用exports
,省略module
let a = 1
exports.a = a
注意
- 导出不可以直接给
exports
赋值,因为本质上导出的是module.exports,当给exports重新赋值对象,exports就会指向新的一块内存空间,它与module.exports的连接就断开了。
具体原因可查看: http://t.zoukankan.com/jianxian-p-12150940.html
// 这样导出的内容会是空对象
let a = 1
let b = 2
exports = {
a, b
}
导入
通过
require
引入
let commons = require('./commons')
console.log(commons) // {a: 1}
动态导入
因为代码发生在运行时,所以可以动态加载代码
let lists = ["./index.js", "./config.js"]
lists.forEach((url) => require(url)) // 动态导入
值的改变
通过add方法修改common.js文件中的a,b值,a,b 不会发生变化
let commons = require('./commons')
let result = commons.add(9,0)
console.log('index2===>',result,commons.a, commons.b) // 9 1 2
注意
- 导入的值是拷贝的,所以可以修改拷贝的值,这会引起变量污染,比如先引入index1.js 再引入index2.js
- 多次加载同一个js, 只会加载一次
// index1.js
let commons = require('./commons')
commons.a = 11
// index2.js
let commons = require('./commons')
console.log(commons.a) // 11
Es Module 用法
导出
导出分为两种:
export
和export default
,两者可以同时存在
ESmodule.js 文件
// 导出单个
export var a = 4
// 导出多个
var a = 4
var b = 22
function add(val1,val2){
a = val1
b = val2
return val1+val2
}
export {
a, b, add
}
// 或者
export default{
a, b, add
}
导入
如果是
export
导出,则用如下方式导入
import {a, b, add} from './ESmodule'
add(7,7)
console.log('index1====>', a) // index1===> 7
// 或者
import * as all from './ESmodule'
console.log('index1====>', all.a) // index1===> 4
如果是
export default
导出, 则用如下方式导入
import esData from './ESmodule'
esData.a = '111'
esData.add(7,7)
console.log('index1====>', esData.a) // index1===>'111'
如果既有
export
又有export default
导出,则用如下方式导入
// 导出
export var a = 4
var b = 22
function add(val1,val2){
a = val1
b = val2
return val1+val2
}
export default {
b add
}
// 导入
import esData, {a} from './ESmodule'
console.log(a, esData.b) // 4 22
值的改变
当是export
导出
- 导出值是值的引用,并且内部有映射关系,所以在导入文件中,不能直接修改值,否则会报错
- 但是可以通过导出文件的方法,修改导出文件的变量,这样会导致污染变量
// 导出文件 ESmodule.js
var a = 4
var b = 22
function add(val1,val2){
a = val1
b = val2
return val1+val2
}
export {
a, b, add
}
// 导入文件
import {a, b, add} from './ESmodule'
a = 4// 不可以直接修改,会报错
add(7,7)
console.log('index1====>', a) // 通过add方法将ESmodule.js中的a的值改变了,这时输出7
当是export default
导出
- 导出值是浅拷贝,所以可以在导入文件中直接修改值
- 但是不能修改导出文件的值
//导出文件 ESmodule.js
var a = 4
var b = 22
function add(val1,val2){
a = val1
b = val2
return val1+val2
}
export default{
a, b, add
}
// 导入文件
import esData from './ESmodule'
esData.a = 4
console.log('index1====>', esData.a) // 可以在导入文件中直接修改值 输出4
add(7,7)
console.log('index1====>', a) // 通过add方法不能将ESmodule.js中的a的值改 输出4
export
和 export default
的区别
- 导出次数不同:
export
可以导出多次,export default
只能导出一次 - 导入方式不同:
export
在导入时要加{ },export default
则不需要,并可以起任意名称 - 值的改变不同:
export
只能在导出文件中改变值,export default
只能在导入文件中改变值
CommonJs 和 Es Module对比
Es Module | CommonJs | |
---|---|---|
输出方式 | export(输出多个) export default(输出一个) | exports(输出多个) module.exports(输出一个) |
加载 | 可以单独加载某个方法(接口) | 加载整个模块,即把所有的接口都加载出来 |
加载时机 | 解析阶段生成接口并对外输出 | 运行阶段加载模块 |
值的变化 | 输出的是值的引用, 原来模块的值改变,则该加载值也变 | 输出的值是拷贝的, 已经加载的值,会使用缓冲, 即原来模块的值改变,不会影响已经加载的该值 |
this指向 | 指向undefned | 指向该当前模块 |