# 模块化
# 1. 关于模块化
所有的编程语言都会面对『模块化』的需求。因为,大家都会遇到 2 个问题:
命名冲突
文件依赖
通过『模块化』可以解决上述两个问题:
模块化就是把单独的一个功能封装到一个模块(文件)中,模块之间相互隔离,但是可以通过特定的接口公开内部成 员,也可以依赖别的模块。
模块化开发的好处:方便代码的重用,从而提升开发效率,并且方便后期的维护。
虽然,我们更常见的是在前端『工程化的项目』中大量使用到模块化,但是,现在的浏览器也支持在普通的、静态的 html 文件中使用模块化。
你只需要做 2 件事情:
将 js 代码写在独立的 .js 文件中,并 export 你想要导出的内容;
在 .html 文件中使用
<script type="module"></script>
引入它,并正确使用 import 即可。
警告
在静态 html 页面中使用多模块,.html 文件不能以双击的方式在浏览器中直接打开,要把它运行访问。最简单的方式,就是在 vscode 中安装 liverserver 插件运行。
# 2. JavaScript 的模块化
JavaScript 引入模块化的概念比较晚。在 ES6 提出模块化规范之前,社区中已经尝试并提出了 AMD、CMD、CommonJS 等模块化规范。不过这些非官方的模块化标准存在一定的局限性。
因此,ES6 语法规范中,在语言层面上定义了 ES6 模块化规范,是浏览器端与服务器端通用的模块化开发规范。
ES6 模块化规范中定义:
每个 js 文件都是一个独立的模块
导入模块成员使用 import 关键字
暴露模块成员使用 export 关键字
『**暴露模块成员**』这个说法有些奇怪,但是其它语言也实现了同样的功能,只不过不是叫这个名字。例如,C++ 和 Java 是以『**访问权限**』实现的类似功能,而 C 语言是以『**本地(静态)变量**』实现的类似功能。
# 3. export 命令
一个模块就是一个独立的文件,文件内部的所有变量外部无法获取。如果希望外部能够读取到模块内部的某个变量,就必须使用 export 关键字输出该变量。
输出(export)变量有 2 种写法:
单个输出
export var firstName = 'Michael'; export var lastName = 'Jackson'; export var year = 1958;
这种写法中,对于(你所想要输出的)每个变量要单独书写
export
(输出几个变量,就要写几个export
)。统一输出
var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year};
这种写法中,你只要书写一个
export
,将你所想要输出的变量都写在这里,写在一起。
export
除了输出变量,还可以输出函数。也分为单个输出和同意输出 2 种写法。
单个输出
export function one(a, b) { ... } export function two() { ... }
统一输出
function one(a, b) { ... } function two() { ... } export { one, two };
# 4. import 命令
使用 export 定义模块的对外接口以后,其它 JS 文件就可以通过 import 来加载这个模块。
import 命令用于加载其它的文件,并从中输入变量。
需要强调的一点是,并非人家 export,你就能直接使用,你需要 import 别人 export 出来的变量和方法,而后你才能用。
import 命令接受一对大括号,里面指定从其它模块导入的变量名(或函数名),大括号里面的变量名必须与被导入模块 export 的“东西”的名称相同。
import { firstName, lastName, year } from './xxx.js';
import 后面的 from 指定模块文件的位置,可以使用相对路径,也可以使用绝对路径。.js
后缀可以省略。
import 命令输入的变量都是『只读』的,即,不允许再加载它的脚本中改写它。如果导入的是一个对象,虽然改写对象的属性是允许的,但是仍不推荐这样使用。
建议凡是 import 的变量,都当作完全只读。若无必要,轻易不要改变它(和它的属性)。
# 5. export default 命令
在使用 import 命令时,import 方需要明确知道 export 方对外导出的变量名或函数名,否则无法加载。这就需要 import 方去阅读 export 方的源码(或文档)。
很显然,这样是很不方便的。更有甚者,export 方对外导出的是匿名对象,或匿名类,这里压根就没名字!例如:
export { ... }
export function() { ... }
这种情况下,你又怎么可能获得它所导出的变量(匿名对象)和函数?
为了给用户提供方便,不用阅读源码(或文档)就能加载模板,可以使用 export default
命令,为模块指定默认输出。
export default { ... }
或
export default function () { ... }
这样,import 方就可以『以任意的名字』去接受这个匿名对象(或匿名函数)。
import obj from 'xxx.js'
或
import sayHello from 'xxx.js'
逻辑上等同于:
const obj = { ... } const sayHello = function () { ... }
需要注意的是,使用 export default 时,对应的 import 命令后面不使用大括号;使用 export 时,对应的 import 需要使用大括号。
毫无疑问,一个模块只能有一个默认输出 export default 。
← ES6 新特性 Promise 对象 →