语法特性
- ES Module自动采用严格模式,或略”use strict”
- 每个ES Module都是运行在自己的私有作用域中
- ES Module是通过”CORS”进行文件请求的,需要请求资源服务端在响应头中添加对应的”CORS”标头。
- ES Module不支持文件的形式访问,需要启动http server的形式来让yem工作起来
- ES Module中的
script
标签会延迟执行脚本—相当于defer
属性
用法
1. 应用模块到HTML
通过给script
标签添加type = "module"
属性,来声明这个脚本是一个模块
1 | <script type="module" src="main.mjs"></script> |
2. 导出模块的功能
ES Module 模块可以多次导出, 且有多种导出方式
注意,单个导出和统一导出,只是对模块成员进行导出的方式不同,若进行了单个导出就不能再进行统一导出了。否则会出现重复导出的错误
而默认导出是指模块文件的默认导出,若对模块成员进行了单个或统一导出,仍然可以规定其为模块默认导出项。
若模块仅需要导出一个模块成员,可以使用单个导出 + 默认导出的方式
若模块需要导出多个模块成员,建议使用统一导出的方式
不建议使用 单个导出 + 统一导出的组合导出方式,因为这种方式不利于代码的可维护性和可读性
1 | //module.js |
3. 导入模块功能
1.导入模块必须使用完整的文件扩展名
2.引用相对路径时,不能省略
./
,否则会解析为加载第三方模块3.可以使用绝对路径引用
4.可以直接引用网络文件(完整的url)
5.可以通过
impirt {} from './module.js'
来执行模块,而不提取模块中的成员 简写为
import './module.js'
导入默认成员
1 | //app.js |
导入统一导出或单个导出成员
1 | //app.ja |
多次分别导入默认成员于普通成员
1 | //app.ja |
一次性导入默认成员于普通成员
1 | //app.ja |
创建模块对象
当模块成员特别多时,可以通过*
的方式提取模块中的所有成员,再通过as
的方式将所有成员全部放在一个对象中.
1 | import * as mod from './module.js |
导入变量文件
import只能出现在文件最顶层,不能嵌套在if语句中。
import也不能使用变量文件名
可以使用import()
函数来导入变量文件名或在代码嵌套中使用,该函数返回一个Promise
对象.
1 | //app.js |
4. 重命名方式
使用as
对导出或导入成员进行重命名
若将导出模块成员重命名为default
,即将模块成员作为模块默认导出成员
导出成员重命名
1 | //module.js |
导入成员重命名
Person作为模块的默认导出成员,可以作为默认成员导入,也可以通过重命名的方式,作为普通模块成员导入
作为默认成员导入,仅需提供一个名称即可
作为普通成员导入,因为default是一个关键词,所以需要对default进行重命名
1 | //app.js |
5.合并模块
想要将模块聚集到一起时,可以将多个子模块聚集到一个父模块。
1 | //main.js |
1 | //app.js |
特殊说明
export { xx1,xx2 }
的语法并不是字面量的导出,import { xx1,xx2 } from "xx.js"
也不是解构赋值。export default { }
导出的是一个对象,表示模块的默认导出成员是一个对象对外导出成员时,导出的是引用关系。模块导入是地址引用,不是拷贝复制。
导入的模块成员是只读的。不能修改导入的模块成员
兼容处理–polyfill
可以在浏览器中直接支持ES Module中的大多数特性
在浏览器中直接
browser-es-module-loader
:在浏览器中直接
为了避免支持ESModule的浏览器重复执行,对polyfill的引用添加nomdule
属性
1 | <script nomodule src="polyfill.js"></script> |
这种方式需要在浏览器运行时编译代码,效率低,正式环境不要使用
通过编译的方式使用
可以使用gulp、webpack等方式编译代码后,在浏览器中使用
Node对ES Module的支持
目前,Node已经提供对ES Module支持的测试版本了
Node 版本需要
>=8.5.0
编译方法
在node中使用ES Module时,需要添加--experimental-modules
的参数,表明启用ES Module的实验特性
注意,若没有进行配置,文件拓展名要修改为mjs
1 | node --experimental-modules test.mjs |
在package.json中配置type
为module
后,ES Module 模块的拓展名可以使用js
1 | { |
运行node --experimental-modules app.js
是可以执行的。
若此时想要使用commonJS模块,需要将commonJS文件的后缀修改为cjs
可以载入node原生模块与第三方模块
1 | import fs from "fs" |
第三方模块需要使用默认导入的方式导入默认成员
对于node原生模块,可以使用提取的方式提取对应模块(官方内置模块做了兼容)
1 | import {writeFileSync} from "fs" |
可以载入CommonJS提供的成员
1 | //common.js |
1 | //esmodule.js |
使用babel实现低版本node兼容ES Module
安装
1 | yarn add @babel/node @babel/core @babel/preset-env --dev |
使用@babel/preset-env
—-插件集合,包含了最新的js标准中的所有新特性
直接使用:
1 | yarn babel-node app.js --presets=@babel/preset-env |
配置@babel/preset-env
后使用,使用preset进行转换配置
在文件.babelrc
中添加
1 | { |
使用:yarn babel-node app.js
使用@babel/plugin-transform-module-commonjs
—- 具体插件:将ESModule转换为CommonJS
1 | yarn add plugin-transform-module-commonjs --dev |
配置@babel/plugin-transform-module-commonjs
,
1 | { |
使用:yarn babel-node app.js