一篇文章搞清JavaScript模块化

题图:by yentl jacobs from Pexels

什么是模块化

模块化是指解决一个复杂问题时自顶向下逐层把系统划分成若干模块的过程,有多种属性,分别反映其内部特性。 ——百度百科

说的简单点就是模块就是实现特定功能的一组方法,模块化将使代码更好的管理、维护和使用

从历史说起

最早,我们这样写代码,

但是,这污染了全局变量,很容易命名冲突。

简单封装:Namespace模式

命名空间模式解决了上面的两个问题:一是全局变量污染的问题,二是可能的名字冲突问题。虽然JavaScript 没有特别支持命名空间, 但命名空间模式在JavaScript中并不难实现,可以把模块写成一个对象,所有的模块成员都放到这个对象里面

上面的函数foo()和bar(),都封装在MYAPP对象里。使用的时候直接调用这个对象的属性即可 。

这虽然减少了全局变量的数量,但是它本质上是对象一点不安全,外部很容易改变内部的状态

IIFE模式:立即执行函数写法

因为函数的局部作用域,使用"立即执行函数"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。

这样function内部的变量就对全局隐藏了,达到是封装的目的。但是这样还是有缺陷的,Module这个变量还是暴漏到全局了,随着模块的增多,全局变量还是会越来越多。

使用了IIFE模式后好像已经有点模块化那意思了,但是如果模块很多,我们一个模块需要另一个模块就需要改改了

上述做法就是我们模块化的基础,目前,通行的JavaScript模块规范主要有两种:CommonJS 和 AMD。当然还有 玉伯的CMD 以及正在逐步普及的ES6 module,还有统一的通用规范UMD(本文不会讲到)

各种模块化规范

在ES6之前 JavaScript 并没有内置的标准模块系统,于是社区的大牛们就制定了一些模块加载方案。

CommonJS

CommonJS 是nodejs也就是服务器端广泛使用的模块化机制。 该规范的主要内容是:模块必须通过module.exports 导出对外的变量或接口,通过 require() 来导入其他模块的输出到当前模块作用域中。

commonJS用同步的方式加载模块,在服务端,模块文件都存在本地磁盘,读取非常快,所以这样做不会有问题。但这在浏览器端问题多多,限于网络原因,更合理的方案是使用异步加载。

AMD和require.js

AMD 即Asynchronous Module Definition,中文名是异步模块定义的意思。它是一个在浏览器端模块化开发的规范。由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,也就是大名鼎鼎 RequireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出

AMD也采用 语句加载模块,但是不同于CommonJS,它要求两个参数:

我们可以来看看前面的例子用 AMD 规范的写法

默认情况下,require.js假定这加载的模块与main.js在同一个目录,然后自动加载。我们可以使用require.config()方法对模块的加载行为进行自定义

requireJS主要解决两个问题

js加载的时候浏览器会停止页面渲染,实现js文件的异步,加载避免网页失去响应;

管理模块之间的依赖性,便于代码的编写和维护;

CMD和sea.js

CMD 即Common Module Definition通用模块定义,CMD规范是国内发展出来的,就像AMD有个requireJS,CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,只不过在模块定义方式和模块加载时机上有所不同:AMD 推崇依赖前置、提前执行,CMD推崇依赖就近、延迟执行。此规范其实是在sea.js推广过程中产生的。

Sea.js 的初衷是为了让 CommonJS Modules/1.1 的模块能运行在浏览器端,但由于浏览器和服务器的实质差异,实际上这个梦无法完全达成,也没有必要去达成。

在 SeaJS 的世界里,一个文件就是一个模块。所有模块都遵循 CMD规范,我们可以像在 Node环境中一样来书写模块代码,我们还是来实现这个加法运算模块:

ES6 Module

值得庆祝的是 ES6 在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。

ES6 模块功能主要由两个命令构成: 和 。 命令用于规定模块的对外接口, 命令用于输入其他模块提供的功能。

参考链接:

CommonJS:http://wiki.commonjs.org/wiki/CommonJSAMD:https://github.com/amdjs/amdjs-api/wiki/AMDrequirejs:http://requirejs.org/CMD:https://github.com/seajs/seajs/issues/242sea.js:http://www.zhangxinxu.com/sp/seajs/ES6 Module:http://es6.ruanyifeng.com/#docs/module

本文完

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180318G12VCF00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券