跟着网站逐步变成"互联网应用顺序",嵌入网页的Javascript代码愈来愈巨大,愈来愈庞杂。
网页愈来愈像桌面顺序,须要一个团队分工协作、进度治理、单元测试等等......开发者不能不运用软件工程的要领,治理网页的营业逻辑。
Javascript模块化编程,已成为一个急切的需求。抱负情况下,开发者只须要完成中心的营业逻辑,其他都能够加载他人已写好的模块。
然则,Javascript不是一种模块化编程言语,它不支撑"类"(class),更遑论"模块"(module)了。(正在制订中的ECMAScript规范第六版,将正式支撑"类"和"模块",但还须要很长时刻才投入有用。)
Javascript社区做了许多勤奋,在现有的运转环境中,完成"模块"的结果。本文总结了当前"Javascript模块化编程"的最好实践,申明怎样投入有用。虽然这不是初级教程,然则只需稍稍相识Javascript的基础语法,就能够看懂。
一、原始写法
模块就是完成特定功用的一组要领。
只需把差别的函数(以及纪录状况的变量)简朴地放在一同,就算是一个模块。
function m1(){
//…
}
function m2(){
//…
}
上面的函数m1()和m2(),构成一个模块。运用的时刻,直接挪用就好了。
这类做法的瑕玷很显著:”污染”了全局变量,没法保证不与其他模块发作变量名争执,而且模块成员之间看不出直接关联。
二、对象写法
为相识决上面的瑕玷,能够把模块写成一个对象,一切的模块成员都放到这个对象内里。
var module1 = new Object({
_count : 0,
m1 : function (){
//…
},
m2 : function (){
//…
}
});
上面的函数m1()和m2(),都封装在module1对象里。运用的时刻,就是挪用这个对象的属性。
module1.m1();
然则,如许的写法会暴露一切模块成员,内部状况能够被外部改写。比方,外部代码能够直接转变内部计数器的值。
module1._count = 5;
三、马上实行函数写法
运用”马上实行函数”(Immediately-Invoked Function Expression,IIFE),能够到达不暴露私有成员的目标。
var module1 = (function(){
var _count = 0;
var m1 = function(){
//…
};
var m2 = function(){
//…
};
return {
m1 : m1,
m2 : m2
};
})();
运用上面的写法,外部代码没法读取内部的_count变量。
console.info(module1._count); //undefined
module1就是Javascript模块的基础写法。下面,再对这类写法举行加工。
四、放大形式
假如一个模块很大,必需分红几个部份,或许一个模块须要继续另一个模块,这时候就有必要采纳”放大形式”(augmentation)。
var module1 = (function (mod){
mod.m3 = function () {
//…
};
return mod;
})(module1);
上面的代码为module1模块添加了一个新要领m3(),然后返回新的module1模块。
五、宽放大形式(Loose augmentation)
在浏览器环境中,模块的各个部份一般都是从网上猎取的,偶然没法晓得哪一个部份会先加载。假如采纳上一节的写法,第一个实行的部份有能够加载一个不存在空对象,这时候就要采纳”宽放大形式”。
var module1 = ( function (mod){
//…
return mod;
})(window.module1 || {});
与”放大形式”比拟,"宽放大形式"就是”马上实行函数”的参数能够是空对象。
六、输入全局变量
独立性是模块的主要特性,模块内部最好不与顺序的其他部份直接交互。
为了在模块内部挪用全局变量,必需显式地将其他变量输入模块。
var module1 = (function ($, YAHOO) {
//…
})(jQuery, YAHOO);
上面的module1模块须要运用jQuery库和YUI库,就把这两个库(实际上是两个模块)看成参数输入module1。如许做除了保证模块的独立性,还使得模块之间的依靠关联变得显著。这方面更多的议论,拜见Ben Cherry的有名文章《JavaScript Module Pattern: In-Depth》。