在編寫jQuery插件時(shí),必須假設(shè)jQuery庫已經(jīng)加載到了頁面中??墒?我們不能假設(shè)$別名一定可用。也有與$別名產(chǎn)生沖突的時(shí)候。
對于代碼比較長的插件來說,很多開發(fā)人員都覺得不能使用$別名會(huì)導(dǎo)致代碼難以理解。為了解決這個(gè)問題,我們可以在插件的作用域內(nèi)定義這個(gè)快捷方式,方法就是定義一個(gè)函數(shù)并馬上調(diào)用它。這種定義并立即調(diào)用函數(shù)的語法通常被稱為立即調(diào)用的函數(shù)表達(dá)式(IIFE,Immediately Invoked Function Expression):
(function($) {//在這里添加代碼
})(jQuery);
這個(gè)包裝函數(shù)只接收一個(gè)參數(shù),我們通過這個(gè)參數(shù)傳入了jQuery對象。這個(gè)參數(shù)的名字是$,因此在這個(gè)函數(shù)內(nèi)部,使用$別名就不會(huì)有沖突了。
jQuery內(nèi)置的某些功能是通過全局函數(shù)提供的。所謂全局函數(shù),實(shí)際上就是jQuery對象的方法,但從實(shí)踐的角度上看,它們是位于jQuery命名空間內(nèi)部的函數(shù)。
使用這種技術(shù)的一個(gè)典型的例子就是$.ajax()函數(shù)。$.ajax()所做的一切都可以通過簡
單地調(diào)用一個(gè)名為ajax()的常規(guī)全局函數(shù)來實(shí)現(xiàn),但是,這種方式會(huì)給我們帶來函數(shù)名沖突的問題。通過把這個(gè)函數(shù)放在jQuery的命名空間內(nèi),我們只需避免它與其他的jQuery方法沖突即可。對想要使用插件的人而言,jQuery命名空間也是一個(gè)提醒,即要使用這個(gè)插件,必須要有jQuery庫。
核心jQuery庫提供的很多全局函數(shù)都是實(shí)用方法;所謂實(shí)用方法,就是一些常用功能的快捷方式,但即使手工編寫同樣功能的代碼也不是很難。數(shù)組處理方法$.each()、$.map()和$.grep()都是實(shí)用方法。為了演示這些實(shí)用方法的創(chuàng)建方式,我們再給jQuery核心庫添加兩個(gè)小函數(shù)。
要向jQuery的命名空間中添加函數(shù),只需將這個(gè)新函數(shù)指定為jQuery對象的一個(gè)屬性即可。
(function($) { $.sum = function(array) {
//在這里添加代碼};
})(jQuery);
于是,我們就可以在使用這個(gè)插件的任何代碼中,編寫如下代碼:
$.sum();
這跟一個(gè)基本的調(diào)用沒什么兩樣,調(diào)用之后就會(huì)執(zhí)行函數(shù)體內(nèi)的代碼。
這個(gè)求和函數(shù)接受一個(gè)數(shù)組作為參數(shù),然后把數(shù)組的值加在一起,最后返回結(jié)果。代碼如下:
(function($) {
$.sum = function(array) {
var total = 0;
$.each(array, function(index, value) {
value = $.trim(value);
value =parseFloat(value) || 0;
total += value;
});
return total;
};
})(jQuery);
注意,我們在這里使用了$.each()方法遍歷了數(shù)組的值。當(dāng)然也可以在此使用for循環(huán),但既然我們能夠確定頁面會(huì)在加載插件之前先加載jQuery庫,使用習(xí)以為常的語法是很自然的。同樣,$.each()的好處在于它的第一個(gè)參數(shù)是一個(gè)對象。
我們的插件在jQuery命名空間中創(chuàng)建了兩個(gè)獨(dú)立的全局函數(shù)。但這樣寫有可能污染命名空間。換句話說,其他jQuery插件也可能定義相同的函數(shù)名。為了避免沖突,最好的辦法是把屬于一個(gè)插件的全局函數(shù)都封裝到一個(gè)對象中,代碼如下所示:
(function($) {
$.mathUtils = {
sum: function(array) {
var total = 0;
$.each(array, function(index, value) {
value = $.trim(value);
value = parseFloat(value) || 0;
total += value;
});
return total;
},
average: function(array) {
if ($.isArray(array)) {
return $.mathUtils.sum(array) / array.length;
}
return '';
}
};
}) (jQuery);
這個(gè)模式的本質(zhì)是為所有的全局函數(shù)又創(chuàng)建了一個(gè)命名空間,叫做jQuery.mathUtils。雖然我們還稱它們?yōu)槿趾瘮?shù),但實(shí)際上它們已經(jīng)成了mathUtils對象的方法了,而mathUtils對象則保存在jQuery對象的屬性中。結(jié)果,在調(diào)用它們時(shí)就必須得加上插件的名字了:
$.mathUtils.sum(sum);
$.mathUtils.average(average);
使用這種技術(shù)(以及足夠獨(dú)特的命名空間),就能夠避免全局函數(shù)污染命名空間。至此,我們已經(jīng)掌握了開發(fā)插件的基本方法。在把這些函數(shù)保存到名為jquery.mathutils.js的文件中之后,就可以將其包含在其他頁面中通過其他腳本來使用這些函數(shù)了。
jQuery中大多數(shù)內(nèi)置的功能都是通過其對象實(shí)例的方法提供的,而且這些方法也是插件之所以誘人的關(guān)鍵。當(dāng)函數(shù)需要操作DOM元素時(shí),就是將函數(shù)創(chuàng)建為jQuery實(shí)例方法的好機(jī)會(huì)。
前面我們已經(jīng)看到,添加全局函數(shù)需要以新方法來擴(kuò)展jQuery對象。添加實(shí)例方法也與此類似,但擴(kuò)展的卻是jQuery.fn對象:
jQuery.fn.myMethod = function() {
alert('Nothing happens.');
};
然后,就可以在使用任何選擇符表達(dá)式之后調(diào)用這個(gè)新方法了:
$('div').myMethod();
當(dāng)調(diào)用這個(gè)方法時(shí)會(huì)彈出一個(gè)警告框。由于這里并沒有在任何地方用到匹配的DOM節(jié)點(diǎn),所以為此編寫一個(gè)全局函數(shù)也是一樣的。由此可見,一個(gè)合理的實(shí)例方法應(yīng)該包含對它的上下文的操作。
未完待續(xù)(_)