小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
ES6导入导出的注意事项
// moudles.js
let name = "jack", age = 18;
let obj = {
name,
age
}
export { name, age }
// app.js
import { name, age } from "./module.js"
// 1. 导出后面的花括号 虽然看着和对象的字面量 一样 但是export 后面的 花括号 是导出的特定的语法, import后面的{ }也不是对象中解构的意思 也是 一种固定的用法
// 导出的 name age是一个引用关系 即导入到app.js中的name 与 moudles.js中的是一个
export default obj //{ name, age }
// 用 export default { name, age } 导出的对象 假如 用 import { name, age } 去导入的话 会报错可见,import后面的{ }也不是对象中解构的意思 是 一种固定的用法
//2. 假如要导出一个对象 ,则要使用 export default 这时 后面的 { }含义与对象字面量中的{ } 一样,export default 后面可以导出一个值
ES Modules导入用法
// app.js
import { name, age } from "./module.js"
// 1. from 后面不能省略.js的扩展名 与 commonJs是有区别的
// 2. commonJs中导入一个文件目录 会自动导入下面的index.js EsModules中是不可以的 必须要补全路径 但是 再用到打包工具后就会 可以省略 index 这个默认路径 和 .js的扩展名了。
// 3."./module.js" 中 ./是不能省略; 可以用/开头的绝对路径 ; 也可以使用完整的url所以可以导入cdn
import { } from "./module.js"
// 简写 import "./module.js" 加载该模块,而不提取它
// 4.假如 import后的{}为空 则会执行该模块,而不会提取任何成员
import * as mod from "./module.js"
// 5.假如导出的成员很多,我们需要全部都导入则可以 使用 * 用as 取一个 别名 这是导入的则会是一个 对象 可以通过mod.属性名 来拿到 对应的成员
import("./module.js").then(module => {
console.log(module);
})
// 6. import这个关键词 只能出现在最顶层
// 假如需要动态导入 则要使用 import() 这个函数 返回值是一个promise
// moudles.js
let name = "jack", age = 18, title = "hello";
let obj = {
name,
age
}
export { name, age }
export default title
// app.js
import { name, age, default as title } from "./module.js"
// 或者
import title, { name, age } from "./module.js" //通过都好分割 ,左边的是默认成员 名字可以随便起
ES Modules 导出导入成员
将导入的结果直接作为结果导出
// app.js
export { foo, bar } from "./module.js"
// 将 import关键词直接修改为export 此时 在当前文件 就不能访问这些成员了
ES Modules 在浏览器中 Polyfill 兼容方案
//生产阶段 不推荐使用 ES Module Loader
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ES Module 浏览器环境 Polyfill</title>
</head>
<body>
<!-- nomodule这个属性可以判断 该浏览器是否支持ES Module 如果没有该属性在支持ES Module的浏览器中将会执行两边代码 -->
<script nomodule src="https://unpkg.com/promise-polyfill@8.1.3/dist/polyfill.min.js"></script>
<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>
<script type="module">
import { foo } from './module.js'
console.log(foo)
</script>
</body>
</html>
ES Modules in Node.js
// 第一,将文件的扩展名由 .js 改为 .mjs;
// 第二,启动时需要额外添加 `--experimental-modules` 参数; node --experimental-modules index.mjs
import { foo, bar } from './module.mjs'
console.log(foo, bar)
// 此时我们也可以通过 esm 加载内置模块了
import fs from 'fs'
fs.writeFileSync('./foo.txt', 'es module working')
// 也可以直接提取模块内的成员,内置模块兼容了 ESM 的提取成员方式
import { writeFileSync } from 'fs'
writeFileSync('./bar.txt', 'es module working')
// 对于第三方的 NPM 模块也可以通过 esm 加载
import _ from 'lodash'
console.log(_.camelCase('ES Module'));
// 不支持,因为第三方模块都是导出默认成员 必须使用默认导入的方式导入
// import { camelCase } from 'lodash'
// console.log(camelCase('ES Module'))
ES Modules in Node.js 与 CommonJS交互
- ESM 导入 commonJs
// commonjs.js
// commonjs 模块始终只会导出一个默认成员
module.exports = {
foo: "CommonJS exports value"
}
//CommonJs 中exports就是 module.exports的一个别名
exports.foo = "CommonJS exports value"
// es-module.mjs
import mod from "./commonjs.js"
console.log(mod) // { foo: "commonjs export value"}
// 1.Es Module 中可以导入CommonJS 模块
- commonJs导入EsM
// es-module.mjs
export const foo = "es module export value"
// commonjs.js
const mod = require("./es-module.mjs")
console.log(mod) //直接载入报错
// 不能在CommonJS模块中通过require载入ES Module
小结
- ES Module中可以导入 CommonJS模块
- CommonJS中不能导入ES Module模块
- 注意!import不是解构导出对象
- CommonJS 模块始终只会导出一个默认成员
ES Modules in Node.js 与 CommonJS的差异
// cjs.js
// 加载模块函数
console.log(require)
// 模块对象
console.log(module)
// 导出对象别名
console.log(exports)
// 当前文件的绝对路径
console.log(__filename)
// 当前文件所在目录
console.log(__dirname)
// esm.mjs
// ESM 中没有模块全局成员了
// // 加载模块函数
// console.log(require)
// // 模块对象
// console.log(module)
// // 导出对象别名
// console.log(exports)
// // 当前文件的绝对路径
// console.log(__filename)
// // 当前文件所在目录
// console.log(__dirname)
// -------------
// require, module, exports 自然是通过 import 和 export 代替
// __filename 和 __dirname 通过 import 对象的 meta 属性获取
// const currentUrl = import.meta.url
// console.log(currentUrl)
// 通过 url 模块的 fileURLToPath 方法转换为路径
import { fileURLToPath } from 'url'
import { dirname } from 'path'
const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
console.log(__filename)
console.log(__dirname)
ES Modules in Node.js新版本的支持
- 在package.json中设置,便不需要将后缀改为 .mjs了 但是commonJs模块的文件 则需要把后缀改为.cjs 才可以使用CommoonJs规范
{
"type": "module"
}
ES Modules in Node.js 兼容方案
//安装 yarn add @babel/node @babel/core @babel/preset-env --dev
// 运行 yarn babel-node index.js --presets=@babel/preset-env
// .babelrc
{
"presets":["@babel/preset-env"]
}
// 运行时不用再加参数 yarn babel-node index.js
// preset 是指一组插件 具体转化是由每一个插件完成的
// 例如只安装 @babel/plugin-transform-modules-commonjs 这个插件
// yarn add @babel/plugin-transform-modules-commonjs --dev
// .babelrc
{
"plugins":["@babel/plugin-transform-modules-commonjs"]
}