js 代码 2009 年 HTML5 兴起后,前端代码的行数已经呈现井喷式发展,随着代码量的增加,模块的缺失的缺点日益凸显,Javascript 社区做了很多探索。如今 JavaScript 模块化编程的概念已经普及开来,一提起模块化,大家想到的可能是 AMD,CMD,requirejs 或 seajs。其实还有很多其他的概念。本文将会陈述下 JavaScript 模块的前世今生。
模块
模块, 又称构件, 是能够单独命名并独立地完成一定功能的程序语句的集合(即程序代码和数据结构的集合体)
一个独立的模块需要能够独立完成一个功能,可以引用依赖和被依赖。例如 C 语言中的库和头文件,Java 中的包,等等。
原始写法
一个函数实际上就是一个模块
// 最简单的函数,可以称作一个模块
function add(x, y) {
return x + y;
}
一个更合理的模拟模块方式
(function (mod, $, _) {
mod.add = ***;
mod.sub = ***;
}((window.mod = window.mod || {}), jQuery, Underscore));
这依旧不完美,因为这个模块必须要先依赖 jQuery 库。理想的情况是,模块的依赖顺序是随意的,我们可以随机顺序指定依赖而不用担心定义先后的问题。
CMD(Common Module Definition)
说道 CMD 就不能不提commonjs,提到 commonjs 就不能不提node。
CMD 规范参照 commonjs 中的方式,定义模块的方式如下:
define(function(require, exports, module) {
// The module code goes here
});
一个文件就是一个模块,文件名就是模块的名字,使用模块的方法也和 commonjs 中一致,只需 require 就好了,模块名字可省略后缀。
// 使用 event.js 模块
var ec = require('event');
CMD 的典型实现就是seajs,应用的很广泛。
AMD(Asynchronous Module Definition)
AMD)是异步模块定义,特别适合在浏览器端使用,其规范和 CMD 是很像的,AMD 规范中定义模块的方式如下:
define(id?, dependencies?, factory);
同 CMD 一样,一个文件即一个模块,模块的使用方法如下:
define(["beta"], function (beta) {
bata.***// 调用模块
});
AMD 主张依赖注入,这点和 CMD 不同(以来查找)。
AMD 也支持已 CMD 的方式来使用依赖。
AMD 的典型实现有 requireJS,modJS 和lodJS。
ES6
ES6带来了语言层面的模块化支持,规范方面见 这里 ,文档方面见 这里。=
UMD
UMD的全称是 Universal Module Definition。和它名字的意思一样,这种规范基本上可以在任何一个模块环境中工作。
一段典型的 UMD 代码如下所示:
(function (root, factory) {
var Data = factory(root);
if ( typeof define === 'function' && define.amd) {
// AMD
define('data', function() {
return Data;
});
} else if ( typeof exports === 'object') {
// Node.js
module.exports = Data;
} else {
// Browser globals
var _Data = root.Data;
Data.noConflict = function () {
if (root.Data === Data) {
root.Data = _Data;
}
return Data;
};
root.Data = Data;
}
}(this, function (root) {
var Data = ...
// 自己的代码
return Data;
}));
这是出自 data.js 中的一部分代码,其原理就是做个判断,不同的环境进行不同的处理。
总结
模块化的探索,使前端工程化成为了可能,可以说没有模块,工程化更无从弹起,