JavaScript 模块化

本文将介绍模块化思想以及 ES6 中的模块化。

一、为什么需要模块化开发?

1. 背景

JavaScript 在设计之初只是一个简单的脚本语言,因此没有模块化的概念,对于复杂代码的组织能力较弱。

随着时代的发展,前端开发人员和代码量激增,协作开发、代码可复用性、代码可维护性显得尤为重要。

2. 问题和解决方法

(1) 全局变量重名问题

在早期开发中,JavaScript 代码往往直接放置在 js 文件中,由不同的程序员开发后再统一引入。这样的开发方式会造成全局变量重名问题:

1
2
3
4
5
6
7
// first.js
var isshow = true;
···

// second.js
var isshow = false;
···

在两个 js 文件中声明了相同的变量,它们之间将会发生冲突,导致变量覆盖,影响代码逻辑。

解决方法:

可以将所有变量与方法放置在自调用函数中,使变量和方法的作用域局限在函数内,从而解决问题。

1
2
3
4
5
6
7
8
9
10
11
// first.js
(function() {
var isshow = true;
···
})()

// second.js
(function() {
var isshow = false;
···
})()

(2) 代码复用问题

如果将变量与方法放置在自调用函数中,又会带来一个新的问题:代码无法复用。

因为无法调用已经写好的函数。

解决方法:

可以采用闭包的方式解决,将所有变量与方法放置在自调用函数中,新建一个对象,在对象中放置希望公开的变量和方法,通过 return 返回并接收。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// first.js
var moduleA = (function() {
var obj = {};
var isshow = true;
function sum(num1, num2) {
return num1 + num2;
}
···
obj.isshow = isshow;
obj.sum = sum;
return sum;
})()

// second.js
console.log(moduleA.sum(1, 2));

二、前端模块化规范

1. 常见模块化规范

  • CommonJS
  • AMD
  • CMD
  • ES6 模块

2. CommonJS 模块化

(1) 导出

1
2
3
4
5
6
module.exports = {
变量1 : 值1,
变量2 : 值2,
方法1 : 方法1,
方法2 : 方法2,
}

(2) 导入

1
var 变量1 = require('路径').变量名

3. ES6 模块

ES6 引入了模块化,分为导出和导入两大部分。

(1) 将 js 文件设为模块化

1
<script type="module"></script>

将 js 文件设置为模块化之后,js 文件中的方法和变量都将是局部变量,仅在文件内有效。

(2) 导出

对象方式:

导出的变量和方法将会放置于对象之中。

1
2
3
4
5
6
export {
变量1,
变量2,
方法1,
方法2,
}
单个方式:
1
export 变量1 = 值

同样会被放置在对象之中

(3) 导入

import 和 export 中的成员名称应该一一对应。

导入之后便可以在文件中使用另一个文件里”暴露”出的变量与方法。

1
import {变量1, 变量2, 方法1, 方法2} from "./文件名.js";

(4) 别名

如果希望为导出/导入的成员设置别名,可以使用 旧名 as 新名

若成员较多,可以采取这样的方式:

1
import * as 对象名 from "./文件名.js";

之后通过 对象.成员名 来访问每个引入的成员。

(5) default

export default 用于向外暴露一个成员,它有且仅能有一个,在其它文件中导入时可以通过任意变量来接收。

1
2
3
export default 成员;

import 任意变量 from "./文件名.js";

import 时可以不用加 {} ,因此有且仅有一个成员。

参考