一、 ES Module 规范特性
通过给 script 添加 type = module 的属性,就可以以 ES Module 的标准执行其中的 JS 代码
<script type='module'></script>
- ESM 自动采用严格模式,相当于在代码添加
‘use strict’
。注意,在严格模式下,this是 undefined;非严格模式this是window。
- 每个 ES Module 都是运行在单独的私有作用域中,外部无法访问内部的成员。
<script type='module'> var foo = 100 </script> <script type='module'> console.log(foo) // => undefined </script>
- ESM 是通过 CORS 的方式请求外部 JS 模块的,对于不支持跨域的文件是请求不到的。
- ESM 的 script 标签会延迟执行脚本(浏览器页面渲染后执行)
二、导出 export
在导出变量时,有两种方式。
1. 变量声明导出
在变量声明时导出,这样只能一次导出一个变量,在使用时不建议
// 导出 --- module.js 文件
export var name = "foo-module"
export function hello () {
console.log("hello")
}
export class Person {}
2. 统一导出
使用 export 统一导出变量时,支持重命名,也可以使用 export default
默认导出一个变量
default
关键字指定单个变量,函数或者类,但是要格外注意一点就是每个模块只能设置一个默认的导出值,也就是说你只能使用一次export default
,若在同一个模块中重复使用了default关键字,它就会报错
// 导出 --- module.js 文件
var name = "foo-module"
function hello () {
console.log("hello")
}
class Person {}
var defaultM = "我是 defaultM"
export {
// as 重命名变量名
name as moduleName,
hello,
Person
}
// 默认导出的变量,在接收时可以使用任意变量名接收
export default defaultM
三、导入 import
静态的 import 语句用于导入由另一个模块导出的绑定。在浏览器中,import
语句只能在声明了type=“module”
的 script标签中使用。
动态 import(),它不需要依赖type=“module”
的 script标签。在 script 标签中使用 nomodule 属性,可以确保向后兼容。
因此静态型的 import 是初始化加载依赖项的最优选择;想要按需加载模块可以使用 动态 import()。
// 导入用法
// 引用模块地址:必须有完整的文件名称;如果是相对路径,地址前的 ./ 不能省略;还可以使用绝对路径或完整的url
import {引入的成员} from 引入模块地址
// 导入整个模块的内容 (将导入的所有成员放入一个对象 mod 中)
import * as mod from './modules.js'
// 只需要执行某个模块(在导入一些不需要外界控制的子功能模块时有用)
import {} from './modules.js'
// import '/modules.js'
// 导入时重命名
import {name as moduleName , hello} from './module.js'
// 导入默认值(默认成员 需要重命名)
import {default as dm , hello} from './module.js'
// 简写 import dm , {hello} from './module.js' 其中 dm 为默认成员,默认成员的名字可以任意取
// 动态导入 模块 (加载模块是异步的过程,)
// import() 必须放在顶层
import('./module.js')
.then(function (module) {
// 回调函数,导入模块的成员可以通过参数取得
})
导出导入模块 注意事项
- export{} 和 import{} 两个都类似于字面量,但不是一样的。它们两个都是固定的语法,用来提取和导出模块内的成员。同时也不同于解构。
- 导入导出模块,无论是否声明了
strict mode
,都会在严格模式下执行 - 例如
export{name}
,这里 通过 export 把 name 导出, 并不是把 name 赋值给了另一个文件,而是将 name 所在的内存空间的一个引用关系给到了另一个文件。所以另一个文件 所访问到的 name 就是 初始定义的那块空间。 import{}
直接导入模块成员的引用地址,因此import 得到的变量与 export 导入的变量在内存中是同一块空间。一旦模块中成员修改了,这里也会同时修改。导入的成员如果是字符串则只读,若是对象,对象内的属性读写不受影响。
// 合并 导入与导出
// import { Button } from './button.js'
// export {Button}
export { Button } from './button.js'