了解es6模块化,看这篇就够了

ES Module

es module 是es6近几年最新出的一个模块化规范。相对于AMD规范,它有了更加严谨的语法标准,使用更加便捷,并且现在大多浏览器都已经支持该特性。

ES 的基本特性

script标签中使用ES

我们只需要给script标签加上一个属性type=module,那么该script就是一个es模块了。而实际上每个js文件也是一个es模块

<script type="module">
// 这就是一个es模块
</script>

自动采用严格模式

对于每个es模块,模块内部会自动采用严格模式,最直观的表现就是,非严格模式下的this指向的是window,严格模式下则this则是undefined

<script>
  console.log(this)
</script>

<script type="module">
  console.log(this)
</script>

结果
在这里插入图片描述

独立的私有作用域

普通的script标签都是全局作用域的,而每个es模块都有独立的私有作用域,很好的解决了命名冲突问题

<script type="module">
  const a = '111'
  console.log(a)
</script>

<script type="module">
  const a = '222'
  console.log(a)
</script>

结果
在这里插入图片描述

ESM通过CORS去请求外部JS模块

这个的意思是,es模块是通过跨域的方式请求外部js模块,所以请求的该js模块必须是支持跨域的,否则会报错

<script type="module" scr="请求的模块路径必须是支持跨域的"></script>

ESM的script脚本会延迟执行

ESM的script脚本会相对与普通的script脚本会延迟执行

<script type="module">
  console.log('我是ESM script')
</script>
<script>
  console.log('我是普通script')
</script>

执行结果
在这里插入图片描述
我们可以看到,虽然es模块的script标签在普通标签前执行,但却是普通标签的内容先打印。这说明esm的script脚本执行比普通的script脚本慢

ES 导入和导出

我们说过,es模块内部都是由私有作用域的,那么如何暴露变量和导入,主要是通过export来暴露变量,import导入变量

export

export <成员声明变量>

export 可以导出成员声明变量,函数,类

// 导出变量,变量可以是任意类型
export const name = 'es module'

// 导出方法
export function foo() {}

// 导出类
export class Person{}

误区
以下这几种导出是错误的,不被支持,export不支持直接导出变量和值

const name = 'aaa'
export name // 导出变量

export 'aaa' // 导出值
export { 变量 }

export还支持导出多个变量,而且在开发的时候用这样方法其实更加的合理,易于观察

const name = 'es module'

function foo () {}

class Person {}

export { name, foo, Person }

这里需要特别注意的是export { name, foo, Person }中的{ }并不是对象,他是export导出变量的一种语法,和function() {}中的{ }是类似的,而且我们上面也说过,export无法直接导出值,因此下面这段代码也是错误的,因为它并不是一个对象,而是一种语法规范,它规定我们就是这样写的

export { 
	name: name,
	foo: foo,
	Person: Person
}
as关键字

如果我们希望对导出的变量名称进行修改,则可以使用as关键字来进行修饰变量 as 别名,但这个方法只适用于export {}

const name = 'es module'

export { name as alias }
default关键字

顾名思义,default代表了一个默认导出的变量,export default可以导出任意的变量或者值

const name = 'es module'

export default name

or

export default { name } // 这里的{},是一个对象

or 

export {name as default} // 这样也可以默认导出name

export{}不同,export default {}中的{}是一个对象,因为export default可以导出任意的变量或者值,所以export default {}导出的就是一个对象,并且使用default关键字后,导入的规则也有所不同,这个后面会讲到。

import

既然有导出,那么久肯定有导入,否则无法去接收导出的变量,常规语法import {} form 'path'

基础用法

对于export导出一样,import同样有特殊的规定,这里我们针对普通的导出,非export default

// 对于普通的导出,非export default
import {name} from './modules.js'
console.log(name)

需要注意的是,和export {}一样,import {} form 'path'中的{ }并不是我们熟悉的解构赋值语法,而是import的一种导入变量的规定规范,这里我们需要区分开来,并且{ }内的变量名称需要和export导出的变量名称相同,否则无法找到对应变量

导入defualt变量

之前说过,普通的export变量和export default变量,在import导入的时候方式稍有不同,export default不需要{ },且可以使用任意变量名称来接收变量

// modules.js
export default 'es module'
import name from './modules.js'
console.log(name)

or

import {default as name} './modules.js'
// log: es module
as关键字

和export一样,import也有as关键字,它也是定义变量的别名

import { name as alias} from './modules.js'

// 也可以接收export default的变量
import { default as alias} from './modules.js'
*关键字

我们有时候需要导入模块内所有的成员变量,但使用常规的方式一个个导入容易出错,而且不方便,这个时候可以使用*关键字

import {a, b, c, d, e} from './modules.js'

// or

import * as param from './modules.js'

console.log(param)
// { ... } param是一个包含所有成员的对象

使用*关键字接收变量的时候一定需要配合as关键字来指定接收所有成员的变量,且最终param接收的结果是一个对象

import导入的变量的特性

使用import {}导入的变量并不是将值拷贝一份,而是指向其变量的地址,所以模块内导出的值发生变化,导入时的变量也会发生变化,且该变量不可被修改(这里的修改是指重新赋值的意思)

  1. 先定义name的值,并导出,1s后修改name的值
// a.js
let name = 'befor'

// 1s后修改模块内的值

setTimeout(() => {
  name = 'after'
}, 1000)

export { name }
  1. 观察导入的name两次打印的结果,并在延时结束后修改name的值
import { name } from './a.js'

console.log(name)
// 2s 后看nam是否修改
setTimeout(() => {
  console.log(name)
  name = 'end' // 重新赋值
}, 2000)
  1. 打印结果
    在这里插入图片描述

可以看到,主文件的name会随着模块内变量的改变而改变,并且无法被修改

接收普通变量和default变量

有可能模块中存在export导出的普通成员变量和default变量的情况,而且在两者导入的方式有差异,那如何在主模块中导入呢?

// 默认值在前,普通变量在后,用逗号隔开,语法可以正常使用
import defaultParam, {normalParam ...} from './modules.js'

// of

import defaultParam, * as nomalParam from './modules.js'
import路径问题

import 导入的路径可以是绝对路径、相对路径和完整的链接,但不可以省略./后缀

动态import

import {} from 'path'中的path不支持变量,且只能定义在开头,如果我们希望使用动态导入则需要使用import('path')方法

// import()返回一个promise,then方法回调接收导入的参数
import('path').then((param) => {
	// param 是导入的成员变量
})

以上内容仅供学习总结和参考,如有疑问欢迎交流

  • 4
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值