一、jQuery源碼
在jQuery中,$是jQuery的別名,執行“$()”就是執行“jQuery()”,執行“$()”返回的是一個jQuery對象,在源碼中,它是這樣定義的:
... var jQuery = function() { return new jQuery.fn.init(); } ... jQuery.fn = jQuery.prototype;
其中,jQuery.fn.init()是一個構造函數,返回的jQuery對象就是通過實例化這個構造函數來創建的,init()在jQuery的原型中被定義:
... var init = jQuery.fn.init = function() { ... return this; } init.prototype = jQuery.fn;
init()構造函數最后返回了這個新對象的引用,並用jQuery的原型覆蓋了init()的原型。
二、分析
如果我們的目的是創建一個jQuery類,它包含了一系列方便我們調用的函數,實例化這個類得到jQuery對象,它可以這么寫:
var jQuery = function() { ... }
jQuery.prototype = { ... }
var jq = new jQuery();
顯然,jQuery不是這樣玩的,而是使用了無new構造:
var jQuery = function(){ return new init(); }
var init = function(){ ... return this; } init.prototype = { ... }
var jq = jQuery();
但是,為了層次更清晰或者其他原因,jQuery將init()構造函數的定義放在了jQuery.prototype里面,即:
var jQuery = function(){ return new jQuery.prototype.init(); } jQuery.prototype.init = function() { ...
return this; } init.prototype = { ... }
關於為什么這么做的原因可以參考這里的討論:https://cnodejs.org/topic/53e73361977012ba5590e66d
此時,還有一個問題:新創建的對象無法訪問jQuery.prototype中的其他屬性,解決方法是:將jQuery.prototype傳遞給jQuery.prototype.init.prototype:
var jQuery = function(){ return new jQuery.prototype.init(); } jQuery.prototype.init = function() { ... return this; } jQuery.prototype.init.prototype = jQuery.prototype;
三、總結
創建jQuery對象的整個流程如下:
1、調用$()方法;
2、調用jQuery.prototype.init()構造函數;
3、根據選擇器不同返回不同的jQuery對象;
4、不同jQuery對象中公用的方法寫在jQuery.prototype中;
5、將jQuery.prototype傳遞給jQuery.prototype.init.prototype,這樣新創建的對象才可以訪問公用方法;