🍉ES6基础-用模块封装代码

2,380 阅读4分钟

「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。

前言

JavaScript 用“共享一切”的方法加载代码,这是该语言中最容易出错且容易令人感到困惑的地方。随着 Web 应用变得更加复杂,JavaScript 代码的使用量也开始增长,这一做法会引起问题,如命名冲突和安全问题。ES6 的一个目标是解决作用域问题,也为了使 JS 应用程序显得有序,于是引进了模块。

1. 什么是模块

模块是自动运行在严格模式下并且没有办法退出运行的JavaScript代码。 模块真正的魔力所在是仅导出和导入你需要绑定,而不是将所有东西都放到一个文件。只有很好地理解了导出和导入才能理解模块和脚本的区别。

2. 导出的基本语法

// 导出数据
export var color = "red";

// 导出函数
export function sum(a, b) {
  return a + b;
}
// 导出类
// 。。。

任何未显示导出的变量、函数或类都是模块私有的,无法从模块外部访问。

3. 导入的基本语法

从模块中导出的功能可以通过 import 关键字在另一个模板中访问。

import { identifier1, identifier2 } from "./example.js";

导入绑定的列表看起来与解构对象很相似,但不是。

导入单个绑定

不能给导入的绑定重新赋值

// 只导入一个
import { sum } from "./example.js";

console.log(sum(1, 2));

sum = 1; // 抛出一个错误

为了更好地兼容多个浏览器和 Node.js 环境,一定要在字符串之前包含/、,/或../来表示要导入的文件。

导入多个绑定

import { sum1, sum2 } from "./example.js";

导入整个模块

// 导入一切
import * as example from "./example.js";

这种导入格式被称为命名空间导入(namespace import)

模块语法的限制

export语句不允许出现在if语句中,不能有条件导出或以任何方式动态导出。模块语法存在的一个原因是要让JavaScript引擎静态地确定哪些可以导出。

4. 导出和导入时重命名

导出重命名

function sum(a, b) {
  return a + b;
}
export { sum as add };

导入重命名

import { add as sum } from "./example.js";

5. 模块的默认值

导出默认值

export default function (a, b) {
  return a + b;
}
function sum(a, b) {
  return a + b;
}
export default sum;

导入默认值

不使用大括号,这种语法是最纯净的。

import sum from "./example.js";

6. 重新导出一个绑定

import { sum } from "./example.js";
export { sum };

你还可以这样写:

export { sum as add } from "./example.js";

7. 无绑定导入

内建对象的共享定义可以在模块中访问,对这些对象所做的更改将反应在其他模块中

例如,要向所有数组添加 pushAll()方法。

Array.prototype.pushAll = function (items) {
  if (!Array.isArray(items)) {
    throw new TypeError("参数必须是一个数组。");
  }
  return this.push(...items);
};

无绑定导入最有可能被应用于创建 Polyfill 和 Shim。

8.加载模块

ES6 并没有尝试为所有 JavaScript 环境一套统一的标准,它只规定了语法,并将加载机制抽象到一个未定义的内部方法 HostResolveImportModule 中。

在 Web 浏览器中使用模块

<script type="module" src="module.js"></script>
<script type="module">
  import { sum } from "./example.js";
  let result = sum(1, 2);
</script>

Web 浏览器中模块加载顺序

<script>元素按照它们被引入的顺序加载。

Web 浏览器中异步模块加载

async 属性应用于脚本时,脚本文件将在文件完全下载并解析后执行。脚本在下载完成后立即执行,而不必等待包含的文档完成解析。

<!-- 无法保证这两个哪个先执行 -->
<script type="module" async src="module1.js"></script>
<script type="module" async src="module2.js"></script>

两个文件都被异步加载,只是简单地看这个代码判断不出哪个模块先执行,原则是谁先加载完谁先执行。

将模块作为 Worker 加载

let worker = new Worker("module.js", { type: "module" });

9. 浏览器模块说明符解析

浏览器说明符要求模块说明符具有以下几种格式之一:

  • 以/开头的解析为从根目录开始
  • 以./开头的解析为从当前目录开始
  • 以../开头的解析为从父目录开始
  • URL 格式

最后

⚽本文介绍了ES6中的模块,模块其实就是一种打包和封装功能的方式~
🏀该篇博客对应的md文档已更新在Github仓库,欢迎Star~
🏉此外笔者还有其他专栏,欢迎阅读~
🏐玩转CSS之美
🎱Vue从放弃到入门
🎳深入浅出JavaScript