jQuery使用有一段時間了,但是有些API的實作實在想不通。小編參考相關資料源碼,現在把我的學習過程和收穫分享給大家。
以下將使用簡化的程式碼來介紹,主要關注jQuery的實作思想~>_
//匿名立即执行函数 //.防止污染全局空间 //.选择性保护内部变量 (function(window, undefined){ //第二参数undefined设置而不传的原因: // 外部发生这种情况:var undefined = 时,undefined会被篡改 // 设置第二参数而不传,则undefined就会被重置回原来值 function jQuery(sel){ return new jQuery.prototype.init(sel); } jQuery.prototype = { constructor: jQuery, init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } } } jQuery.prototype.init.prototype = jQuery.prototype; //对外暴露jQuery:将jQuery绑定在window上面 window.$ = jQuery; })(window);
--------------------------
jQuery一開始使用匿名立即執行函數包裹其內部,並在第5行對外暴露;
所謂的匿名立即執行函數即這個函數是匿名的(沒有名字)、定義完後立即調用的;
當我們在外部呼叫$("div")時,其實呼叫的就是內部的jQuery("div");
(function(window, undefined){ //内部变量 //对外暴露jQuery:将jQuery绑定在window上面 window.$ = jQuery; })(window); $("div")
--------------------------
好,接下來稍微複雜點,下面的程式碼主要實作如圖的互相引用:
以$('div')呼叫為例:
從第2行程式碼可以看出,jQuery使用jQuery.prototype.init來實例化jQuery對象,但這會帶來一個問題:
實例化的物件只能存取到init下的變量,而不能存取到jQuery.prototype(jQuery對外提供的API綁定在該物件下)。
於是乎,補寫第21行程式碼,將init.prototype指向jQuery.prototype即可。
這樣就完成了,使用init來實例化,並且可以在init作用域下存取到jQuery.prototype。
function jQuery(sel){ return new jQuery.prototype.init(sel); } jQuery.prototype = { constructor: jQuery, init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } } } jQuery.prototype.init.prototype = jQuery.prototype;
為什麼要用jQuery.prototype.init來實例化對象,而不直接使用jQuery函數呢?
假設使用jQuery函數來實例化對象,這樣對象之間的引用的確可以簡化為 jQuery-->jQuery.prototype。
但是呼叫會變得繁瑣起來:new $('div'),所以基於這個考慮(猜測(⊙0⊙)),在內部使用較為複雜的實現,來簡化呼叫。
--------------------------
好,最後,再來看一下init的實作。同樣也簡化了程式碼,只實現了最常用的一種情況。
jQuery會把獲取到的nodeList處理成數組(方便後續使用),並在其下掛載一些變量,如length,selector。
init: function(sel){ if(typeof sel === 'string'){ var that = this; //jQuery内部使用的是Sizzle,这里使用querySelectorAll替代 var nodeList = document.querySelectorAll(sel); Array.prototype.forEach.call(nodeList, function(val, i){ that[i] = val; }) this.selector = sel; this.length = nodeList.length; } }
本文所述到此結束,下篇文章將給大家介紹jQuery鍊式調用與show知識淺析,欲了解更多資訊敬請關注腳本之家網站!