1. 程式人生 > >jQuery原始碼解析(架構與依賴模組)一、理解架構

jQuery原始碼解析(架構與依賴模組)一、理解架構

一、設計原理

輕量級的js庫,相容CSS3,相容各種瀏覽器(IE6.0+,FF1.5+,Safari2.0+,Opera9.0+),Jquery2.0及後續潘奔不在支援IE6/7/8瀏覽器。jQuery一個比較大的優勢是,它的文件說明很全,並且各種應用很詳細,同時還有許多成熟的外掛提供。核心:The Write Less,Do More(寫更少,做更多)。簡潔的API、優雅的鏈式、強大的查詢與便捷的操作,使的jQuery成為前端世界的一把利劍!

二、整體架構

13個核心方法
// 核心方法
// 回撥系統
// 非同步佇列
// 資料快取
// 佇列操作
// 選擇器引
// 屬性操作
// 節點遍歷
// 文件處理
// 樣式操作
// 屬性操作
// 事件體系
// AJAX互動
// 動畫引擎
五大模組:
選擇器、DOM操作、事件、AJAX與動畫

三、立即呼叫表示式

任何庫和框架設計第一要點就是解決名稱空間與變數汙染的問題,jQuery利用了JS函式作用於的特性,採用‘立即呼叫表示式’包裹了自身的方法來解決這個問題。
寫法1.
(function (window,factory) {
		factory(window);
	}(this,function () {
		return function () {
			//jQuery的呼叫
			alert(12);
		}	
	}));

形參 window和factory,實參this、函式,factory(window)中的window為一個實參,this代表window
上面的程式碼程式碼程式碼中嵌套了兩個函式,把其中的一個函式作為引數傳遞到另一個函式中,並且執行,我們可以簡化一下寫法:如下
寫法2.
var factory = function () {
		return function () {
			//執行方法
			alert(12);
		}
	};
	var jQuery = factory(); //此時表達的是返回的函式
上面的程式碼效果和方法一是等同的,但是卻有點變成了簡單的工廠方法模式,需要自己去呼叫,下面我們再次改進: 寫法3.
(function (window,undefined) {
		var jQuery = function () {}
			// ...
			window.jQuery = window.$ = jQuery;
				$();
	})(window);

四、jQuery的類陣列物件結構

為什麼jQuery能像陣列一樣操作,為什麼能通過物件get方法或則直接通過下標0索引就能轉化成DOM物件
jQuery的入口統一是$,通過傳遞引數的不通,實現9種方法的過載,
1. jQuery([selector,[context]])
2. jQuery(element)
3. jQuery(elementArray)
4. jQuery(object)
5. jQuery(jQuery object)
6. jQuery(html,[ownerDocument])
7. jQuery(html,[attributes])
8. jQuery()
9. jQuery(callback)
分為三大塊:選擇器、dom的處理、dom載入,換句話說,jQuery就是為了獲取DOM、操作DOM,
所有,為了更方便這些操作,讓節點與例項物件通過一個橋樑給關聯起來,jq內部採用一種叫‘類陣列物件’的方式作為儲存結構,即可以像物件一樣處理jq物件,也能像陣列一樣可以使用push、pop、shift、unshift、sort、map等類陣列的方法操作jq物件。
舉個栗子 :
var aQuery = function(selector) {
    //強制為物件
	if (!(this instanceof aQuery)) {
		return new aQuery(selector);
	}
	var elem = document.getElementById(/[^#].*/.exec(selector)[0]);
	this.length = 1;
	this[0] = elem;
	this.context = document;
	this.selector = selector;
	this.get = function(num) {
		return this[num];
	}
	return this;
}
 1、強制為物件,第一次執行時,通過instanceof判斷原型是否是aQuery,第一次顯然不是,並通過new建立一個新的aQuery物件。  2、正則中的^代表的是以什麼開頭,[]代表包含的內容,[^]則代表不包含的內容。返回的是除了#之外的內容,因為是陣列,所有要使用[0]來獲取。

五、jQuery中的ready與load事件

jQuery中三種文件的載入方式 : 1.
$(document).ready(function () {
	// body...
});
2.方式1的簡寫
$(function () {
	// body...
});
3.
// $(window).load(function () {
// 	// body...

// });   //如果不支援此方法的使用,則需要在window中新增事件監聽來實現
大家在面試的時候,經常被問到一個問題,ready和load哪一個先執行,答案是ready先執行,load後執行。下面看一下DOM文件的載入步驟 : (1) 解析HTML結構。
(2) 載入外部指令碼和樣式表文件。
(3) 解析並執行指令碼程式碼。
(4) 構造HTML DOM模型。//ready 、DOMContentLoaded
(5) 載入圖片等外部檔案。
(6) 頁面載入完畢。//load
由上可以看出,兩者的區別是資原始檔的載入,ready構建基本的DOM結構,一般使用ready,這樣網站頁面載入速度更快,而load需要載入完圖片等資源才去處理框架的載入。
// jquery文件載入時機
jQuery.ready.promise = function (obj) {
	if(!readyList){
		readyList = jQuery.Deferred();
		//表示頁面已經載入完成,直接呼叫 ready方法
		if (document.readyState === "complete") {
			//將 jQuery.ready壓入非同步訊息佇列,設定延遲時間1毫秒(注意,有些瀏覽器延遲不能小於4毫秒)
			setTimeout(jQuery.ready);
		}else{
			 //監聽DOM載入完成
			document.addEventListener("DOMContentLoaded",complete,false);
			//這裡是為了確保所有ready執行結束,如果DOMContentLoaded方法執行了,將有一個狀態值 isReady被設定為true,因此,
			 //ready方法一旦執行,那麼將只執行一次,window.addEventListener中的ready 將被 return 中斷
			window.addEventListener("load",complete,false)
		}
	}
	return readyList.promise(obj);
}

六、jQuery多庫共存處理

多庫共存換句話可以叫‘無衝突處理’,主要由於jQuery採用$作為名稱空間,不免會與別的框架或外掛產生衝突,jQuery給出一個方案--noConflict函式,此函式將$符號的控制權讓給其他的庫,而使用jQuery來代替$符號
比如:$('name') 換成jQuery('name')
var _jQuery = window.jQuery,
    _$ = window.$;

jQuery.noConflict = function(){
	if( window.$ === jQuery){
		window.$ = _$;
	}
	if(deep && window.jQuery === jQuery){
		window.jQuery = _jQuery;
	}
	return jQuery;
}	
//上面的函式必須在匯入jQuery檔案之後,並且需要有相同$作為名稱空間的庫。
//首先將外部的window.$賦予_$,在noConflict中進行判斷,如果沒有交出控制權則將window.$與之前儲存的_$替換。

本文參考資料為 : http://www.imooc.com/code/3093