jQuery 源碼解析代碼及更多學習乾貨: 猛戳GitHubhtml
建議下載源碼而後據文章思路學習,最好本身邊思考邊多敲幾遍。前端
myjQuery-1.0.1.js
(這個文件是用來仿寫jQuery).myjQuery-1.0.1.js
文件.本次主要剖析jQuery選擇器的封裝,在平時使用jQuery時,很是容易的經過$()就能夠查找相關的選擇器,那麼具體是如何實現的呢?跟隨我來一探究竟...node
首先先來作個例子: 咱們先經過官方的jQuery框架輸出如下幾個實例:jquery
// 傳入字符串
console.log($("a")); //建立DOM節點包裝成jQuery對象
// 傳入HTML
console.log($("<div>")); // //建立DOM節點包裝成jQuery對象
// 傳入對象
console.log($(document));
// 傳入選擇器
console.log($('.box'));
// 傳入對象
console.log($(this)); // 把傳入的對象包裝成jQuery對象
// 傳入方法
$(function(){
console.log(11111); //這個是在頁面加載完成後加載執行的,等效於在DOM文檔加載完成後執行了$(document).read()方法
})
複製代碼
輸出結果:git
根據輸入的結果咱們類閱讀源碼,反推如何實現相似的效果: 首先$()調用的是jQuery.prototype.init()的初始化方法,因此要在init()方法裏作擴展。init:function (selector,context) {
context = context || document;
var match,elem,index=0;
if(!selector){
return this;
}
/**
* 檢測傳過來的數據是不是字符串
* **/
if(typeof selector === "string"){
if (selector.charAt(0) === "<" && selector.charAt(selector.length-1)=== ">" && selector.length>=3) {
// 此時是HTML
match = [selector];
}
// match 有值的狀況
if (match) {
/**
* 合併數組
* merge parseHTML是靜態擴展方法
* **/
jQuery.merge(this, jQuery.parseHTML(selector,context));
// 查詢DOM節點
} else {
elem = document.querySelectorAll(selector);
// 轉化爲真數組
var elems = Array.prototype.slice.call(elem);
this.length = elem.length;
for (;index = elem.length;index ++) {
this[index] = elems[index];
}
this.context = context;
this.selector = selector;
}
// HANDLE: $(DOMElement)
} else if (selector.nodeType){ //
this.context = this[0] = selector;
this.length = 1;
return this;
// $(function)
// 函數處理
} else if (isFunction( selector )) {
jQuery(document).ready(selector); // 實例對象的方法
}
/**
*makeArray 是jQuery擴展的方法
**/
return jQuery.makeArray( selector, this );
},
複製代碼
jQuery 擴展的靜態方法
/**
* 合併數組
* [first] jQuery的實例對象 this
* [second] DOM 節點
*/
merge:function (first,second) {
var l = second.length, // 1
i = first.length, // 0
j = 0;
if (typeof l === "number") {
for ( ; j < l; j++){ // 遍歷DOM節點
first[i++] = second[j];
}
} else {
while (second[j] !== undefined) {
first[i++] = second[j++];
}
}
first.length = i;
// 返回jQuery的實例對象
return first;
},
/**
* 解析HTML
* [data] 傳入的數據
* [context] 返回的值
* **/
parseHTML:function (data,context) {
if (!data || typeof data !== "string") {
return null;
}
/**
* exec() 是正則方法 返回爲數組
* [0] 爲正則表達式相匹配的文本
* [1] 表達式相匹配的文本
* **/
// 過濾掉符號,只提取標籤 "<a>" ==> "a"
var parse = rejectExp.exec(data);
// 返回一個建立DOM的元素
return [context.createElement(parse[1])];
},
/**
* 將一個類數組對象轉換爲真正的數組對象
* [arr] 傳入的數組
* [result] 返回的數組
* **/
makeArray:function(arr,result){
var ret = result || [];
if ( arr != null ) {
if ( isArrayLike( Object( arr ) ) ) {
jQuery.merge( ret,
typeof arr === "string" ?
[ arr ] : arr
);
} else {
[].push.call( ret, arr );
}
}
return ret;
},
isReady:false,
readylist:[],// list
ready:function(){ // 事件函數
jQuery.isReady = true;
jQuery.readylist.forEach(function(callback){
callback.call(document);
})
// 清空
jQuery.readylist = null;
}
});
複製代碼
/**
* 定義全局函數
* **/
// 判斷是不是方法
var isFunction = function isFunction( obj ) {
return typeof obj === "function" && typeof obj.nodeType !== "number";
};
// 判斷是不是windows
var isWindow = function isWindow( obj ) {
return obj != null && obj === obj.window;
};
複製代碼
經過以上代碼能夠作如下幾點分析:
1.$()傳過來的selector數據是屬於什麼類型?不一樣的數據類型,分析不一樣數據類型的行爲,有如下幾種狀況:
github
經過剖析jQuery選擇器模塊,進行測試:正則表達式
測試代碼:windows
// 建立DOM
// 傳入字符串
console.log($("a")); //建立DOM節點包裝成jQuery對象
// 傳入HTML
console.log($("<div>")); // //建立DOM節點包裝成jQuery對象
// 傳入對象
console.log($(document));
// 傳入選擇器
console.log($('.box'));
// 傳入對象
console.log($(this)); // 把傳入的對象包裝成jQuery對象
$(function(){
console.log(11111);
複製代碼
輸出結果:設計模式
至此完美收官 !! 😊經過剖析jQuery源碼選擇器部分,有如下幾點我的收穫:
數組
jQuery 源碼剖析 系列目錄地址:猛戳GitHub
jQuery 源碼剖析 系列預計寫十篇左右,旨在加深對原生JavaScript 部分知識點的理解和深刻,重點講解 jQuery核心功能函數、選擇器、Callback 原理、延時對象原理、事件綁定、jQuery體系結構、委託設計模式、dom操做、動畫隊列等。
若是有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。若是喜歡或者有所啓發,歡迎 star⭐️,對做者也是一種鼓勵。
關注公衆號回覆:學習 領取前端最新最全學習資料,也能夠進羣和大佬一塊兒學習交流