2009年,大名鼎鼎的美国程序员Ryan Dahl创造了nodeJs项目,将javascript语言用于服务器端编程。
这标志"Javascript模块化编程"正式诞生。因为老实说,在浏览器环境下,没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,否则就无法与操作系统和其他应用程序互相调用,开发起来也相当不方便。 nodeJs的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。假定有一个数字计算模块math.js,就可以像下面这样加载: var math = require('math'); 然后,就可以调用模块提供的方法: var math = require('math'); math.add(1,2); // 3 因为这个系列主要针对浏览器编程,不涉及nodeJs,所以对CommonJS就不多做介绍了。我们在这里只要知道,require()用于加载模块就行了。 人类科技进步能有如此发展之迅猛一个重要的原因就是人类会根据事物联想,有了服务器端模块以后,自然而然大家就想要客户端模块。而且最好两者能够兼容,一个模块不用修改,在服务器和浏览器都可以运行。 然而,由于历史的局限性,使得CommonJS规范不适用于浏览器环境。为什么?还是上面的代码,如果要在浏览器中运行,会有一个或许大多数人都想不到的问题,你能看出来吗? 原因就是第二行math.add(1, 2)在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用的执行就会卡在那里死等。 这在服务器端是不会有任何问题的,因为服务器端所有的模块都存放在本地磁盘,可以很快的同步加载完成,等待时间就是磁盘的读取时间。但是,在浏览器上,这就是一个不折不扣的问题,因为模块文件都在服务器端,等待的时间取决于用户网速的快慢,网速快还好说,网速慢就呵呵了。 由此来看,浏览器端的模块,是一定不能采用"同步加载"(synchronous)的,只能采用"异步加载"(asynchronous)。就这样,AMD规范诞生了。 AMD是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面代码的执行。所有依赖这个模块的语句,都定义在一个回调函数中,等到加载完成之后,回调函数才会运行。 AMD也采用require()语句加载模块,不同于CommonJS的是,它要求两个参数: require([module], callback); 第一个参数[module],是一个数组,里面的元素就是要加载的模块的名字;第二个参数callback,则是加载成功之后的回调函数。如果将上面例子的代码改写成AMD形式,就是下面这样: require(['math'], function (math) { math.add(1, 2); }); 这样,math.add()方法会等到math模块加载完成才会执行,这样就不会阻塞应用的执行。所以很显然,AMD是非常适合浏览器环境的。
目前,主要有两个Javascript库实现了AMD规范:require.js(用的很广)和curl.js。下一篇将会说说require.js的使用,以及如何将模块化编程投入实际开发中。