感覺jQuery1.5最大的改變有兩個,jQuery子類與非同步列隊,本文只談jQuery子類。
首先要明白為何要推出此功能,是強化它那基本為零的OO功能嗎?不是,從下面的源碼你應該知道它不是讓你自訂類。但這也是個愚蠢的問題,因為這樣,這方法就叫Class,而不是subclass。
subclass: function(){function jQuerySubclass( selector, context ) {return new jQuerySubclass.fn.init( selector, context );}jQuerySubclass.superclass = this;jQuerySubclass.fn = jQuerySubclass.prototype = this();jQuerySubclass.fn.constructor = jQuerySubclass;jQuerySubclass.subclass = this.subclass;jQuerySubclass.fn.init = function init( selector, context ) {if (context && context instanceof jQuery && !(context instanceof jQuerySubclass)){context = jQuerySubclass(context);}return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );};jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;var rootjQuerySubclass = jQuerySubclass(document);return jQuerySubclass;},
我想它真正的用意是為了改善其外掛程式機制。
jQuery的外掛程式是很容易開發,隨便在其原型鏈上添加個方法就叫稱“外掛程式”,因此jQuery的外掛程式很多,垃圾外掛程式也很多,由於停止更新變成垃圾的也很多。
jQuery.fn.garbage = function(){ alert("這是垃圾外掛程式!") }
當然這是在最理想的情況下,外掛程式才這麼簡單(好像一個函數算一個外掛程式也蠻多的)。比如你開發一個外掛程式,然後你同事也開發了一個同名的外掛程式,這時出問題吧。還有這種情況:
(function($){//外掛程式一 $.fn.extend({ a:function(){//外掛程式的主體 this.b() }, b:function(){}//輔助函數 }) })(jQuery); (function(){//外掛程式二 $.fn.extend({ c:function(){//外掛程式的主體 this.b() }, b:function(){}//輔助函數 }) })(jQuery);
這時這兩個外掛程式混用就有問題了,外掛程式一的b與外掛程式二的b可能不是一個東西,這機率還很大,因為外掛程式一可能是美國的菜鳥開發,外掛程式二是德國的菜鳥開發的,而且外國人都非常喜歡把他們的外掛程式放到jQuery官網的外掛程式展示區,國內的懶鬼兼菜鳥就很容易踩雷了。
外掛程式混亂之災隨著jQuery的流行日益嚴重,由於jQuery易學易用,公司前端不夠人手,隨便抓個後台就行了。於是前端也像中國樓市那樣出現泡沫了,一個頁面引用N個外掛程式,滿屏的選取器,維護成本超高,近乎不可能。
歸根結底,問題是大家都在汙染jQuery與jQuery.fn這個兩個對象,就像以前大家都愛到全域範圍那裡拉屎那樣。全域範圍是公廁,去那兒是不可避免的,但我們可以用子類來轉移jQuery,jQuery.fn的負擔。
在jQuery1.5中,我們就應該這樣寫外掛程式。
var MyjQuery = jQuery.subclass();MyjQuery.fn.writeHello = function(){ this.text('Hello World'); };MyjQuery('p').writeHello();
由於MyjQuery是jQuery的子類,因此擁有其所有能力,鏈式操作一樣沒問題。
MyjQuery('div').css('border', '1px red solid').writeHello();
我們還可以對jQuery原有方法進行修改,不用因為某些隱性bug而改源碼了:
MyjQuery.fn.text = function(val) { var orig = jQuery.fn.text; if(typeof val === "string") { return orig.call(this, "!!"+ val +"!!"); } else { return orig.apply(this, arguments); }};MyjQuery('.aaa').text("text");MyjQuery('.aaa').text();//!!text!! //不影響jQuery自身jQuery('.aaa).text('text'); //text
當然這也帶來一個問題,外掛程式都變為綁定到新的命名空間上了,重新跑到全域範圍上拉屎……看來進一步的救贖要等其包載入機制出來了。因此少用外掛程式,提高自身的javascript(非jQuery)能力才是基本。