模块化(二):模块化的规范——AMD

上次我们说到,现阶段比较流行的js模块化是 CommonJSAMD

目前前端使用的较多的是AMD,但是在说AMD之前,先要了解到CommonJS

CommonJS

其实一开始浏览器端没有模块化也是没有什么很大的关系的,因为网页程序的复杂性有限;但是后台的小伙伴说,在服务器端,必须要有模块,与操作系统和其他应用程序互动。
是为了弥补JavaScript标准库过少的缺点而产生的,JS没有模块机制,CommonJS就帮助JS实现模块的功能。
eg:现在很热门的Node.js就是CommonJS规范的一个实现。
但是其实CommonJS也有一个很大的弊端:
浏览器除了本地缓存的资源,所有的资源都必须从服务器下载下来,这个加载的时间也需要根据当时的网速而定,而commonJS的加载是同步阻塞的,必须要加载完上一个才能继续下一个,就导致,如果中间有个文件是很大的,那么后面的就必须要停止,等待前面的加载完成,才能继续。

AMD

AMD 全称 The Asynchronous Module Definition,AMD规范也就是“异步模块定义规范”,是 RequireJS在推广过程中对模块定义的规范化产出。(AMD)制定了定义模块的规则,这样模块和模块的依赖可以被异步加载。这和浏览器的异步加载模块的环境刚好适应(浏览器同步加载模块会导致性能、可用性、调试和跨域访问等问题)。

规范只定义了一个函数 “define”,它是全局变量。函数的描述为:
$$ define(id?, dependencies?, factory); $$

id (名字)

id,是个字符串。它指的是定义中模块的名字,这个参数是可选的。如果没有提供该参数,模块的名字应该默认为模块加载器请求的指定脚本的名字。如果提供了该参数,模块名必须是“顶级”的和绝对的(不允许相对名字)。

dependencies (依赖)

dependencies,是个定义中模块所依赖模块的数组。依赖模块必须根据模块的工厂方法优先级执行,并且执行的结果应该按照依赖数组中的位置顺序以参数的形式传入(定义中模块的)工厂方法中。
依赖的模块名如果是相对的,应该解析为相对定义中的模块。换句话来说,相对名解析为相对于模块的名字,并非相对于寻找该模块的名字的路径。

本规范定义了三种特殊的依赖关键字。如果”require”,”exports”, 或 “module”出现在依赖列表中,参数应该按照CommonJS模块规范自由变量去解析。

依赖参数是可选的,如果忽略此参数,它应该默认为[“require”, “exports”, “module”]。然而,如果工厂方法的形参个数小于3,加载器会选择以函数指定的参数个数调用工厂方法。

factory(工厂方法)

factory,为模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。
如果工厂方法返回一个值(对象,函数,或任意强制类型转换为true的值),应该为设置为模块的输出值。

用AMD规范实现一个简单的模块可以这样

创建一个名为”alpha”的模块,使用了require,exports,和名为”beta”的模块:

1
2
3
4
5
6
7
define("alpha", ["require", "exports", "beta"], function (require, exports, beta) {
exports.verb = function() {
return beta.verb();
//Or:
return require("beta").verb();
}
});

一个返回对象的匿名模块:

1
2
3
4
5
6
7
define(["alpha"], function (alpha) {
return {
verb: function(){
return alpha.verb() + 2;
}
};
});

一个没有依赖性的模块可以直接定义对象:

1
2
3
4
5
define({
add: function(x, y){
return x + y;
}
});

一个使用了简单CommonJS转换的模块定义:

1
2
3
4
5
define(function (require, exports, module) {
var a = require('a'),
b = require('b');
exports.action = function () {};
});

全局变量

  1. AMD规范保留全局变量”define”以用来实现本规范。包额外信息异步定义编程接口是为将来的CommonJS API保留的。模块加载器不应在此函数添加额外的方法或属性。
  2. 保留全局变量”require”被模块加载器使用。模块加载器可以在合适的情况下自由地使用该全局变量。它可以使用这个变量或添加任何属性以完成模块加载器的特定功能。它同样也可以选择完全不使用”require”。

参考资料

1.AMD in github
2.阮一峰:AMD规范

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×