今天来介绍 JavaScript 的模组 esm
系统及 commonjs
系统。
当我们的程序越写越复杂时,不再适合把几千行的程序码全部放在同一个档案内,这样不仅难以更新维护,发生错误时也难以及时发现处理。
所以我们会将程序码拆成一块一块,把相似功能的程序码放到一个一个档案中,再一层一层的引用。这样不仅维护相对容易,在做部分项目更新时也较为方便,避免误触不相干的程序码外,在思考时也较能专注在相关程序码上。
这样拆成一个一个的档案,再用引用的方式使用,我们就可将之称为模组。
最早 JavaScript 是没有模组设计的,因为通常都是被 HTML 一个个 <script>
引入使用。
也因此当时爲 JavaScript 设计模组的责任就落到了开发者身上,所以出现许多不同的第三方模组系统,其中较为知名的应该是 commonjs
、umd
及 amd
了。
後来又经过了几年,在 2015 年时随着 ES6 的正式发布,JavaScript 终於迎来了标准版本的模组系统,称为 esm
。
随着时间的流逝,也因为标准模组系统 esm
的出现,许多第三方模组系统就慢慢被遗弃了。不过,也不是全部的第三方模组系统都被 esm
取代了,像是因为 Node.js 预设使用的模组系统是 commonjs
,所以其生态仍是非常丰富,开发者社群也相当活跃。而 umd
因为可以直接使用,不需要额外的引用方式,在 <script>
可以直接引用的特性,也还是有一定的可见性。
所以接下来会对 esm
及 commonjs
做较为详细的解说。
esm
作为标准的模组系统,其重要性近年来持续上升,对其的支援也越趋广泛。
esm
用了非常好懂的 export
及 import
关键字来定义模组的汇出物件,以及引用时使用的物件。
常见的 export
方式:
// mod.js
const cool_things = {
c1: "我是常数",
f1() {},
f2() {},
};
export default cool_things;
// or
export { ...cool_things };
两种 export
的差异在於 import
时的可用性。
export default
,可以用任意名称 import
,而另一个方法则否。
// 使用 export default 时的 import 方法
// 两者会引入相同东西至不同名称物件中
import things from "./mod.js";
import something from "./mod.js";
// 使用 export { ... } 时的 import 方法
// 可以选择引入其中数项,不需全部引入
import { c1, f2 } from "./mod.js"; // 只引入 c1 及 f2
需要注意的是,import
会在一开始时就引入,且会等所有模组皆被引入後再执行其余程序。
因为 import
的优先引入可能会引入不必要的模组或阻挡主程序的运行,所以 esm
中还有一种动态引用的方法 import()
,其会回传一个 Promise
包着的 module。
(async () => {
doSomethingWithoutModule();
const mod = await import("./mod.js");
mod.doSomething();
})();
记得要加上 type="module"
attribute 才能使用。
CommonJS 作为 Node.js 长久以来使用的模组系统,当然在使用 Node.js 时会用到啦。
require
是 CommonJS 用来引入模组的函式。
const mod = require("./mod.js");
// 或是只引入部分
const { c1, f2 } = require("./mod.js");
require
可以在任何地方使用,不一定要在档案最上面引用,可以依判断条件动态引用不同模组等。
exports
及 module.exports
则是用来汇出模组物件的。
exports
其实就是 module.exports
,就好像是系统已经帮你写好了 var exports = module.exports;
一样。
const cool_things = {
c1: "我是常数",
f1() {},
f2() {},
};
// 汇出 cool_things
module.exports = cool_things;
// 或分项汇出
exports.c1 = cool_things.c1;
exports.f1 = cool_things.f1;
exports.f2 = cool_things.f2;
exports.c2 = "我是另一个常数";
其实 exports
物件就可以想成是这个模组对外的介面。
以 9/20 12:00 ~ 9/21 12:00 文章观看数增加值排名
+321
深入浅出 Computed
+246
Day 2:什麽是 SRE
+210
#1 JavaScript Easy Go!
+205
LeetCode 是什麽?为什麽要刷题?
+204
LeetCode 解题的思考策略与解题地图
+201
Day 1 无限手套 AWS 版:掌控一切的 5 + 1 云端必学主题
+199
[Day 02] 什麽是tinyML?
+199
[Day 02] 什麽是tinyML?
+194
#4 Array & Object in JavaScript
+181
Proxmox VE 安装虚拟机:Windows 10 (一)
AWS 称霸 2 天後就几乎全部消失了
说到 LeetCode,让我想起了 LeetCode Stats Card
>>: #06 No-code 之旅 — 用 Next.js 解决前後端?API Routes 简介
Hej,我是Charlie! 在Day07当中,我们完成了基本的登入跟登出,而在今天我们将完成JWT...
-1. 序 OK,资料分析做完了, 现在要进入演算法的部分, 我们未来几天将从经典卷积神经网路架构中...
Chap.IV Data Services 资料库服务 SQL Databases SQL 资料库 ...
表单组件 使用表单处理使用者输入是常见的应用的基础功能,使用这些表单组件可以应用在注册、登入、电商…...
●Java 自定义注解 创建自定义注解类似於编写接口,不同之处在於interface关键字以@符号为...