前段時間在閱讀javaScript基於原型的面向對象編程相關資料時,對一直在使用的jQuery產生了點疑問,便對其稍作了點研究。
在javascript編程中,生成對象的方式有兩種,
第一種,對象字面量方式:
var foo = {
name : "紅一葉",
age : 18
};
第二種就是通過構造器方式創建對象:
function Foo(){
this.name = "紅一葉";
this.age = 18;
}
var foo = new Foo();
在上式中,foo便是由構造器Foo構造出來的對象(在javascript中,函數都可以作為構造器。於是有個不成文的約定,凡是要作為構造器使用的函數首字母大寫)。
回到jQuery中,在jQuery中我們最為常用的對象生成方式$("#id"),很顯然這種方式和上面兩種都不像,讓我們通過代碼來看看jQuery到底做了什么封裝和轉換(以下代碼取自於jQuery1.9.1);
window.jQuery = window.$ = jQuery;
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
},
通過上面幾行代碼我們可以看出,jQuery和$是兩個等價的全局變量,$("#id")便是調用了上面定義的函數,等價於jQuery("#id"),這個函數的返回值是new jQuery.fn.init( selector, context, rootjQuery );
也就是說$("#id")其實是調用了init()構造器構造了一個對象並返回。
咱們再細看一下jQuery.fn.init();這個jquery.fn是個什么東東,已及init構造器到底有什么特殊的地方?來咱再上代碼來看看
jQuery.fn = jQuery.prototype = {
init: function( selector, context, rootjQuery ) {
......
},
....
};
jQuery.fn.init.prototype = jQuery.fn;
由jQuery.fn = jQuery.prototype這句可以看出fn是jQuery原型對象的一個引用,實際上fn也沒有其他特別的含義,為防止給我們的思維造成混亂,可以把上面代碼中的所有fn用jQuery的原型替代(即把所有的jQuery.fn替換成jQuery.prototype)。
至於init構造器有什么特殊的地方,上面我們看到,jQuery中把init的原型指向了jQuery.fn即指向了jQuery的原型,jQuery.prototype。這樣做的好處在於,由init()構造器構造的對象就能夠通過原型鏈訪問到jQuery原型上的方法和屬性。
對於這幾個變量的關系,如果有疑問的話可以參照下面的兩張圖來幫助理解,第一張是我自己畫的,第二張百度上借網友的,表示的都是一個意思,只是畫的方式不同而已。