大前端 - ES Modules

特性

  • 通过给 script 添加 type="module" 的属性,就可以以 ES Module 的标准执行其中的 JS 代码
  • ESM 自动采用严格模式,忽略 “use strict”
  • 每个 ES Module 都是运行在单独的私有作用域中
  • ESM 是通过 CORS 的方式请求外部的 JS 模块的
  • ESM 的 script 标签会延迟执行脚本,不会阻滞页面的渲染

导入导出

 // 导出 module.js
var name = 'foo module'
function = hello () { console.log('hello') }
class Person {}
export { name, hello, Person }
export { name as fooName, hello as fooHello } // 导出时重命名,重命名之后,别的文件导入时只能用重命名之后的命名

export { name as default }
// ==>
export default name  // 将 name 作为默认导出,导入时则必须重命名
  
 // 导入 demo.js
 import { name } from './module.js'
 import { name as fooName } // 导入时重命名

注意事项

  • 导入时,导入的本质是对模块内容的地址引用,即导入的成员与导出的成员是同一个对象,而非对原有对象的深拷贝
// module.js
var name = 'jack'
var age = 19
export { name, age }
setTimeout(function() {
    name = 'ben'
}, 1000)

// demo.js
import { name, age } from './module.js'
console.log(name, age)
setTimeout(function() {
    console.log(name, age)
}, 1500)
  • 导入的成员是只读的,即执行文件中不能对导入的成员进行修改
name = 'tom' // Uncaugth TypeError
  • 导入时,必须使用完整的路径名,不能省略拓展名
import { name } from './module' // Not Found 
  • 通过相对路径引用本地模块时,必须加上 “./”,否则会被判定为引用第三方模块
  • 只需要执行 module ,而不需要引用模块中的值时,可以引用的 { } 为空,或者直接引用模块
import {} from './module.js'
// ==>
import './module.js'
  • 需要导入模块中的所有数据,可以用 * 来引入,引入时可以通过 as 的方式将模块中的成员存放到一个对象中,导出的成员则会作为该对象的属性
import * as mod from './module.js'
console.log(mod.name)
  • 动态加载模块
import('./module.js').then(function (module) {
    console.log(module)
})

早期版本浏览器兼容

// 引入
// 添加 nomodule 属性,可以使模块只在不兼容 module 的环境下引用
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/babel-browser-build.js"></script>
<script nomodule src="https://unpkg.com/browser-es-module-loader@0.4.1/dist/browser-es-module-loader.js"></script>
// IE 不支持 Promise,所以需要做额外兼容
<script nomodule src="https://unpkg.com/promise-polyfill@8.1.3/dist/polyfill.js"></script>

Node.js 环境

  • 文件扩展名需要更改为 .mjs
  • 命令行中执行需要加上执行参数 --experimental-modules
node --experimental-modules index.mjs
// 因为目前这个特性还是属于实验特性,不建议直接使用

与 CommonJS 交互

  • 在 ES Module 中导入 CommonJS 模块
    • CommonJS 始终只导出一个默认(default)成员
    • 不能直接提取成员,import 不是结构导出的对象
// commonjs.js
module.exprots = {
    foo: 'commonjs exports value'
}

// es-module.mjs
import { foo } from '/commonjs.js'
console.log(foo) // Error
  • 在 CommonJS 中导入 ES Module
// es-module.mjs
export const foo = 'es module export value'

// commonjs.js
const mod = require('./es-module.mjs')
console.log(mod) // Error

与 CommonJS 的差异

ESM 中没有 CommonJS 中的那些模块全局成员,所以无法直接引用对应的成员函数

  • CommonJS
// 加载模块函数
console.log(require)
// 模块对象
console.log(module)
// 导出对象别名
console.log(exports)
// 当前文件的绝对路径
console.log(__filename)
//当前文件所在目录
console.log(__dirname)
  • ES Module
import { fileURLToPath } from 'url'
import { dirname } from 'path'

// 当前文件的绝对路径
const __filename = fileURLToPath(import.meta.url)
console.log(__filename)

//当前文件所在目录
const __dirname = dirname(__filename)
console.log(__dirname)

总结

  • ES Module 中可以导入 CommonJS 模块
  • CommonJS 中不能导入 ES Module 模块
  • CommonJS 始终只会导出一个默认成员
  • import 不是解构导出对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值