jQuery 是一個非常優秀的 JS 庫,與 Prototype,YUI,Mootools 等眾多的 Js 類庫相比,它劍走偏鋒,從 web 開發的實用角度出發,拋除了其它 Lib 中一些中看但不實用的東西,為開發者提供了優美短小而精悍的類庫。其使用簡單,文件豐富,而且效能高效,能極大地提高 web 系統的開發效率。因此可以說是 web 應用開發中最佳的 Js 輔助類庫之一。大部分開發者正在拋棄 Prototype,而選擇Jquery 做為他們進行 web 開發的 JS 庫。

如是開發人員僅僅只知道文件中的簡單的使用方法,卻不明白 Jquery 的執行原理和內部機制,在使用 jquery 時,肯定會碰到許多的問題。這些問題有一部分是 Jquery 的 Bug。大部分是自身的使用不當而造成的。而文件的簡單的使用說明很難解決問題。在除錯基於 jQuery 的 web 應用時,很多時候都要跟蹤進入jQuery 物件分析其執行狀態以瞭解出錯的原因。
如果對於 web 的應用的頁面執行效能和效率有所要求的話,那麼我們更應該去明白其執行機理和核心原始碼。
而且,學習jQuery原始碼的設計思想也是會有很大的收穫的。
 
本筆記以jQuery-2.0.3原始碼為準:
 
先把筆記(一)分三部分介紹:最終將會得出整個jQuery的基本結構
一、
介紹:
jQuery原始碼框架組成 匿名函式自執行的優點 匿名函式對外介面設定 window下掛載$()與jQuery() jQuery.prototype 原型、jQuery 基於面向物件的程式 jQuery函式呼叫與jQuery物件呼叫方法 jQuery中繼承方法:extend jQuery擴充套件工具方法:$.trim()、$.proxy()…… 靜態方法和例項方法的關係和區別簡要說明。
 
由於原始碼過於龐大複雜,所以先把基本框架搭出來:
整個程式碼都包含在一個自執行的函式裡面:
(function(){

})();

這樣有什麼好處呢?

就是在函式裡面寫的任何東西都是區域性的,在外部都是無法用到裡面的變數和方法的。這樣就可以與其他程式碼防止衝突,互相不影響。

但是都把東西弄成區域性的也不行,還得提供介面:有一種方法就是把要對外提供的介面給它掛載到window下面,這時候呼叫就可以直接用了:

  (function(){
var a = ;
function $(){
alert(a);
};
window.$ = $;
})(); $();

給出原始碼的基本結構:

(function(){

  [,]:變數和方法;jQuery = function(){};

  [,]:給jQuery這個物件新增一些方法和屬性;

  [,]:extend JQ的繼承等等

  [,]:jQuery.extend({{}):拓展一些工具方法

  [877,2856]:完成一個Sizzle的功能

  [2880,3042]:jQuery當中的回撥物件callbacks:通過回撥函式去管理函式,即函式的統一管理

  []:window.jQuery = window.$ = jQuery;

})()

[21行,94行]:定義了一系列的變數和函式。

[61行]:jQuery = function(){}; 這個jQuery就是平時咱們用的$()或者jQuery()去找元素的一個對外的介面。但是它目前是一個區域性函式,要怎麼樣才能在外面找到它呢?這是就要對外提供一個介面,就在[8826行],把函式掛載在了window下的jQuery或者$。

[96行]:jQuery.fn = jQuery.prototype = {};因為原型prototype在JavaScript中是屬於面向物件的東西,所以可以說jQuery就是一個基於面向物件的東西。為什麼jQuery是一個基於面向物件的程式:可以使用類比來說一下,可以說這樣寫可以提高可讀性吧。

比如我們平時在用jQuery的時候,寫法是這樣的:
$(".div").css();
$(".div").html();
就好比:
var arr = new Array();
arr.sort();
arr.splice();
這都是一種面向物件的寫法

不過這裡$(".div")是函式呼叫,只是它的執行結果是物件:[63行]如下:

jQuery = function( selector, context ) {
// The jQuery object is actually just the init constructor 'enhanced'
return new jQuery.fn.init( selector, context, rootjQuery );
}
//返回的是一個jQuery物件

[285,347]:extend這個是一個繼承的方法。使用繼承方法更加有利於程式碼的獨立性、後期的維護還有拓展;

[349,817]:jQuery.extend({{}):拓展一些工具方法。拓展工具方法優勢什麼呢?如下:

在jQuery當中提供了兩種程式碼操作方式
比如:
$().css();
$().html();$()是物件,所以兩個方法屬於例項的方法。可以看做是更高階的東西 $.trim();
$.proxy();$只是一個函式,函式下面拓展一些靜態的方法。這個就叫拓展工具方法。與上面的區別就是即可以給jQuery用,也可以給原生的JS來用。可以看做是更底層的東西

二、

介紹:jQuery中近2000多行:Sizzle選擇器 jQuery中的Sizzle:複雜選擇器的實現 jQuery中的Callbacks:JQ中的回撥物件(函式統一管理) jQuery中的Deferred:延遲物件(非同步統一管理) jQuery中的support:瀏覽器功能檢測。

[877,2856]:完成一個Sizzle的功能。

sizzle的作用就是:複雜選擇器的實現。我們平時做一些比如這樣類名的選擇器都是$(".div")都是比較簡單的,還有複雜的:$("ul li + p input.class")。他也可以是一個獨立的東西,平時不使用jQuery的時候也可以用它,http://sizzlejs.com/

/*!
* Sizzle CSS Selector Engine v1.9.4-pre
* http://sizzlejs.com/
*
* Copyright 2013 jQuery Foundation, Inc. and other contributors
* Released under the MIT license
* http://jquery.org/license
*
* Date: 2013-06-03
*/

[2880,3042]:jQuery當中的回撥物件callbacks:通過回撥函式去管理函式,即函式的統一管理。

為什麼要管理:因為函式又多又複雜,統一管理起來可以方便使用。如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="jquery-2.0.3.js"></script>
<script type="text/javascript">
function fn1(){alert("");}
function fn2(){alert("");} var cb = $.Callbacks(); cb.add(fn1);
cb.add(fn2); cb.fire(); //1,2.統一地放在一起
</script>
</head>
<body>
</body>
</html>

不止這些,還有執行一次啊、去重啊、刪除啊等等。Callbacks可以加引數的。如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="jquery-2.0.3.js"></script>
<script type="text/javascript">
function fn1(){alert("");}
function fn2(){alert("");} var cb = $.Callbacks(); cb.add(fn1);
cb.add(fn2); cb.fire(); cb.remove(fn1); cb.fire();
</script>
</head>
<body>
</body>
</html>

對函式的管理非常有幫助。

[3043,3183]:實現的功能是:延遲物件:Deferred。作用就是對非同步的統一管理。

因為JS中非同步方式很多,這樣做有利用管理。比如:

        setTimeout(function(){
alert("");
},);
alert("");

先彈2,在彈1。但是正常的邏輯思維應該是先寫先執行,後寫後執行,這樣容易看懂,後期維護也方便。如果沒有延遲物件的管理,要實現這樣的彈出順序就得這樣寫了:

        setTimeout(function(){
alert("");
alert("");
},);

這樣就非常彆扭了,影響開發。延遲物件就可以解決這樣的問題:

        var dfd = $.Deferred();

        setTimeout(function(){
alert("");
dfd.resolve();
},); dfd.done(function(){
alert("");
})

這樣就會先出1再出2了。

利用回撥的方式:先把dfd.done()裡面的引數儲存,但觸發了dfd.resolve()後就會執行done()裡面的引數。所以如果將dfd.resolve()這句去掉的話就不會彈出2了。

[3184,3295]:support:功能檢測。

什麼是功能檢測呢:有時我們會判斷瀏覽器的版本等資訊來決定執行什麼樣的操作,但是現在的瀏覽器更新非常快,功能也層出不窮。所以如果只是單單判斷瀏覽器的版本等資訊對維護是非常不利的。但是我們如果根據功能來判斷瀏覽器就比較靠譜了,因為瀏覽器升級過程中功能肯定會保留。比如:

[3198行]
// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)
support.checkOn = input.value !== "";

當我們寫input的型別為checkbox/radio的時候,瀏覽器會預設為“on”,但是老版本webkit預設為“”,所以要區分老版本webkit和其他瀏覽器就可以通過support.checkOn了。

三、

介紹:jQuery中的data:資料快取(避免大資料量的元素掛載、預防記憶體洩露) jQuery中的queue、dequeue:佇列管理(入隊、出隊管理) jQuery中的attr、prop、val、addClass等:元素屬性操作 jQuery中的on、trigger等:事件操作的相關方法 jQuery中的DOM操作:新增、刪除、獲取、包裝、篩選…… jQuery中的CSS方法:樣式的操作 jQuery中的資料提交與ajax:跨域、請求script、ajax…… jQuery中的animate:運動方法的實現 jQuery中的offset:位置與尺寸的方法 jQuery中的模組化:jQuery中支援模組化的模式。

[3308,3652]:data()方法的功能:資料快取。就是對資料進行的一些操作:獲取、設定、刪除。如下:(當然這種方式只是舉例,實際並不這麼用)

        $(".div").data('name','hello');  //新增一個數據

        $('.div').data('name');    //獲取一個數據

[3653,3797]:queue():佇列管理;dequeue():出隊

jQuery中哪裡會用到呢:比如運動的效果,如下:

$('.div').animation({left:});
$('.div').animation({top:});
$('.div').animation({width:});

先left、再top、最後再width,就是利用佇列來保證順序的。

[3803,4299]:attr(),prop(),val(),addClass()等等方法:對元素屬性的操作。

[4300,5128]:on(),trigger()等方法:事件操作的相關方法。

[5240,6057]:DOM操作方法:新增,刪除,獲取,包裝,DOM篩選。

[6058,6620]:css():樣式的操作。

[6621,7854]:提交的資料和AJAX操作:ajax(),load(),getJson().

[7855,8584]:animate():運動方法。

[8585,8792]:offset():位置和尺寸的方法。

[8804,8821]:jQuery支援模組化的一個模式。

最終的結構如下:

(function(){

    ( , ) 定義了一些變數和函式 jQuery = function(){};

    ( , ) 給JQ物件,新增一些方法和屬性

    ( , ) extend : JQ的繼承方法

    ( , ) jQuery.extend() : 擴充套件一些工具方法

    ( , )  Sizzle : 複雜選擇器的實現 

    ( , ) Callbacks : 回撥物件 : 對函式的統一管理

    ( , ) Deferred : 延遲物件 : 對非同步的統一管理

    ( , ) support : 功能檢測

    ( , ) data() : 資料快取

    ( , ) queue() : 佇列方法 : 執行順序的管理 

    ( , ) attr() prop() val() addClass()等 : 對元素屬性的操作

    ( , ) on() trigger() : 事件操作的相關方法

    ( , ) DOM操作 : 新增 刪除 獲取 包裝 DOM篩選

    ( , ) css() : 樣式的操作

    ( , ) 提交的資料和ajax() : ajax() load() getJSON()

    ( , ) animate() : 運動的方法

    ( , ) offset() : 位置和尺寸的方法

    ( , ) JQ支援模組化的模式

    ()  window.jQuery = window.$ = jQuery;

})();