共计 3808 个字符,预计需要花费 10 分钟才能阅读完成。
前言
初衷: 将我整顿的笔记分享给大家,心愿本篇文章能给你带来不一样的认知,不喜勿喷。
适宜人群: 前端高级开发,大佬绕道。
内容构造: 为什么有模块化 -> 根本语法 -> 两者区别。
为什么会有 CommonJs 和 Es Module 呢
咱们都晓得在晚期 JavaScript
模块这一概念,都是通过 script
标签引入 js
文件代码。当然这写根本简略需要没有什么问题,但当咱们的我的项目越来越宏大时,咱们引入的 js
文件就会越多,这时就会呈现以下问题:
- js 文件作用域都是顶层,这会造成变量净化
- js 文件多,变得不好保护
- js 文件依赖问题,略微不留神程序引入错,代码全报错
为了解决以上问题 JavaScript
社区呈现了 CommonJs
,CommonJs
是一种模块化的标准,包含当初的 NodeJs
外面也采纳了局部 CommonJs
语法在外面。那么在起初 Es6
版本正式退出了 Es Module
模块,这两种都是解决下面问题,那么都是解决什么问题呢。
- 解决变量净化问题,每个文件都是独立的作用域,所以不存在变量净化
- 解决代码保护问题,一个文件里代码十分清晰
- 解决文件依赖问题,一个文件里能够分明的看到依赖了那些其它文件
那么咱们上面来一一理解它们的语法及弊病吧
CommonJs 根本语法
导出
CommonJs
中应用 module.exports
导出变量及函数,也能够导出任意类型的值,看如下案例。
// 导出一个对象
module.exports = {
name: "蛙人",
age: 24,
sex: "male"
}
// 导出任意值
module.exports.name = "蛙人"
module.exports.sex = null
module.exports.age = undefined
间接导出
导出也能够省略 module
关键字,间接写 exports 导出也能够,看如下案例。
exports.name = "蛙人"
exports.sex = "male"
留神:如果应用 exports 导出单个值之后,就不能在导出一个对象值,这会批改以后导出的援用,然而之前的导出就会被笼罩。
exports.name = "蛙人"
export.sex = "male"
exports = {name: "蛙人"}
下面 example 中,这种状况会扭转对象的援用值,所以最初导出的只是一个对象。
混合导出
混合导出,exports
和 module.exports
能够同时应用,不会存在问题。
exports.name = "蛙人"
module.exports.age = 24
导入
CommonJs
中应用 require
语法能够导入,如果想要单个的值,能够通过解构对象来获取。
// index.js
module.exports.name = "蛙人"
module.exports.age = 24
let data = require("./index.js")
console.log(data) // {name: "蛙人", age: 24}
反复导入
不论是 CommonJs
还是 Es Module
都不会反复导入,就是只有该文件内加载过一次这个文件了,我再次导入一次是不会失效的。
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 根本语法
导出
在 Es Module
中导出分为两种,单个导出 (export
)、默认导出(export default
),单个导出在导入时不像CommonJs
一样间接把值全副导入进来了,Es Module
中能够导入我想要的值。那么默认导出就是全副间接导入进来,当然 Es Module
中也能够导出任意类型的值。
// 导出变量
export const name = "蛙人"
export const age = 24
// 导出函数也能够
export function fn() {}
export const test = () => {}
// 另一种模式导出
const sex = "male"
export sex
// 如果有多个的话
const name = "蛙人"
const sex = "male"
export {name, sex}
混合导出
能够应用 export
和export default
同时应用并且互不影响,只须要在导入时中央留神,如果文件里有混合导入,则必须先导入默认导出的,在导入单个导入的值。
export const name = "蛙人"
export const age = 24
export default = {fn() {},msg: "hello 蛙人"
}
导入
Es Module
应用的是 import
语法进行导入。如果要单个导入则必须应用花括号 {}
, 留神:这里的花括号跟解构不一样。
// index,js
export const name = "蛙人"
export const age = 24
import {name, age} from './index.js'
console.log(name, age) // "蛙人" 24
// 如果外面全是单个导出,咱们就想全副间接导入则能够这样写
import * as all from './index.js'
console.log(all) // {name: "蛙人", age: 24}
混合导入
混合导入,则该文件内用到混合导入,import
语句必须先是默认导出,前面再是单个导出,程序肯定要正确否则报错。
// index,js
export const name = "蛙人"
export const age = 24
export default = {msg: "蛙人"}
import msg, {name, age} from './index.js'
console.log(msg) // {msg: "蛙人"}
下面 example 中,如果导入的名称不想跟本来地名称一样,则能够起别名。
// index,js
export const name = "蛙人"
export const age = 24
export default = {msg: "蛙人"}
import {default as all, name, age} from './index.js'
console.log(all) // {msg: "蛙人"}
导入值的变动
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 是动态
就是 Es Module
语句 `import
只能申明在该文件的最顶部,不能动静加载语句,Es Module
语句运行在代码编译时。
if (true) {import xxx from 'XXX' // 报错}
总结
Es Module
也是解决了变量净化问题,依赖程序问题,Es Module
语法也是更加灵便,导出值也都是导出的援用,导出变量是可读状态,这增强了代码可读性。
CommonJs 和 Es Module 的区别
CommonJs
- CommonJs 能够动静加载语句,代码产生在运行时
- CommonJs 混合导出,还是一种语法,只不过不必申明后面对象而已,当我导出援用对象时之前的导出就被笼罩了
- CommonJs 导出值是拷贝,能够批改导出的值,这在代码出错时,不好排查引起变量净化
Es Module
- Es Module 是动态的,不能够动静加载语句,只能申明在该文件的最顶部,代码产生在编译时
- Es Module 混合导出,单个导出,默认导出,齐全互不影响
- Es Module 导出是援用值之前都存在映射关系,并且值都是可读的,不能批改
感激
谢谢各位在百忙之中点开这篇文章,心愿对你们能有所帮忙,如有问题欢送各位大佬斧正。
我是蛙人,如果感觉写得能够的话,请点个赞吧。
感兴趣的小伙伴能够退出 前端娱乐圈交换群 欢送大家一起来交换探讨
往期好文
《带你轻松了解数据结构之 Map》
《这些工作中用到的 JavaScript 小技巧你都晓得吗?》
《了解数据结构之 Set,只有 5 分钟!》
《【倡议珍藏】分享一些工作中罕用的 Git 命令及非凡问题场景怎么解决》
《解构:使数据拜访更便捷!》
《你真的理解 ES6 中的函数个性么?》
《一看就懂的 var、let、const 三者区别》