介绍
多年来,可供选择的JavaScript组件的生态系统不断地稳步增加。有很多的选择固然是很好的一件事,但是各个组件混合搭配使用的时候会带来不少的问题,开发者不会花很多时间就会发现所有组件使用起来总有这样那样的问题。
为了解决这些问题,互为竞争对手的模块规范 AMD 和 CommonJS 出现了,它们可以让开发者在约定的沙箱以模块化的方式编写自己的代码,以免“污染生态系统”。
CommonJS
CommonJs 是一种 JavaScript 语言的模块化规范,它通常会在服务端的 Nodejs 上使用。项目是由多个模块组成的,模块和模块之间的调用,需要各个模块有相同规范的 API,这样一来在使用的过程中不会有那么多的学习成本,并且对于单个模块来说是类聚的。
在 CommonJs 的模块化规范中,每一个文件就是一个模块,拥有自己独立的作用域、变量、以及方法等,对其他的模块都不可见。CommonJS规范规定,每个模块内部,module 变量代表当前模块。这个变量是一个对象,它的 exports 属性(module.exports)是对外的接口。加载某个模块,其实是加载该模块的 module.exports 属性。require 方法用于加载模块。
下面就是采用CommonJS规范的foo模块写法。
//module-a.js
module.exports = {
a:1
}
//module-b.js
var ma = require('./module-a'); var b = ma.a + 2; module.exports = {
b:b
};
CMD
CMD 叫做通用模块定义规范(Common Module Definiton),它是类似于 CommonJs 模块化规范,但是运行于浏览器之上的,关于模块化的好处我们在 CommonJs 篇文章中我们了解过。它是随着前端业务和架构的复杂度越来越高运用而生的,来自淘宝玉伯的 SeaJS 就是它的实现。
CMD 规范尽量保持简单,并与 CommonJS 的 Modules 规范保持了很大的兼容性。通过 CMD 规范书写的模块,可以很容易在 Node.js 中运行。在 CMD 规范中,一个模块就是一个文件。格式如下:
definde(factory)
具体使用方法如下:
// moudle-a.js define(function(require, exports, module) { module.exports = { a: 1 }; }); // moudle-b.js define(function(require, exports, module) { var ma = require('./moudle-a'); var b = ma.a + 2; module.exports = { b: b }; });
AMD
define(id?, dependencies?, factory);
// moudle-a.js define('moudleA', function() { return { a: 1 } }); // moudle-b.js define(['moudleA'], function(ma) { var b = ma.a + 2; return { b: b } });
UMD: 通用模块定义
UMD 叫做通用模块定义规范(Universal Module Definition)。也是随着大前端的趋势所诞生,它可以通过运行时或者编译时让同一个代码模块在使用 CommonJs、CMD 甚至是 AMD 的项目中运行。未来同一个 JavaScript 包运行在浏览器端、服务区端甚至是 APP 端都只需要遵守同一个写法就行了。
它没有自己专有的规范,是集结了 CommonJs、CMD、AMD 的规范于一身,我们看看它的具体实现:
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('jquery')); } else { // Browser globals (root is window) root.returnExports = factory(root.jQuery); } }(this, function ($) { // methods function myFunc(){}; // exposed public method return myFunc; }));
保持同样的模式实现更复杂的例子:
(function (root, factory) { if (typeof define === 'function' && define.amd) { // AMD define(['jquery', 'underscore'], factory); } else if (typeof exports === 'object') { // Node, CommonJS-like module.exports = factory(require('jquery'), require('underscore')); } else { // Browser globals (root is window) root.returnExports = factory(root.jQuery, root._); } }(this, function ($, _) { // methods function a(){}; // private because it's not returned (see below) function b(){}; // public because it's returned function c(){}; // public because it's returned // exposed public methods return { b: b, c: c } }));