jQuery-1.9.1源碼分析系列(一)整體架構


不廢話,直接上關鍵。這個系列中有好些直接借用別人的資料,我將他們整合在自認為比較合理的地方。所以在此先謝謝那些前輩。

注意:后續系列中jQuery實例多用$(...)來表示

1.    初始化與鏈式調用基礎


 

jQuery之所以能夠鏈式調用在於每次調用返回來jQuery本身。實現關鍵代碼如下。

 

jQuery = function(selector,context){
  return new jQuery.fn.init(selector,context,rootjQuery);
}
...
rootjQuery = jQuery(document);
...
jQuery.fn = jQuery.prototype = {
  constructor: jQuery,
  init: function(selector,context,rootjQuery){
    ...
    return this;     ... } } ... jQuery.fn.init.prototype = jQuery.fn; ... window.jQuery = window.$ = jQuery;

  

需要有幾個理解

a.    new的深度理解


 var obj = new Base();

這樣代碼的結果是什么,我們在Javascript引擎中看到的對象模型是:

 

new操作符具體干了什么呢?其實很簡單,就干了三件事情。

var obj = {};

obj.__proto__ = Base.prototype;

Base.call(obj);

第一行,我們創建了一個空對象obj;

第二行,我們將這個空對象的__proto__成員指向了Base函數對象prototype成員對象;

第三行,我們將Base函數對象的this指針替換成obj,然后再調用Base函數,於是我們就給obj對象賦值了一個id(name,根據瀏覽器決定,chrome是name屬性)成員變量,這個成員變量的值是”Base”。

 

Base函數返回的結果會導致obj的結果不同。

舉例(chrome下):

function Base(){
  this.name = “test”;
  this.a = “f”;
  return result;
}

1)     根據new的原理,如果沒有返回值或返回值為數字或字符串或布爾類型,即result為null/number/string/bool,則new Base()返回的結果是本身,為

Base {name: "test", a: "f"}

2)     如果返回值為對象(數組或普通對象)或函數,則返回的對象或函數替換了Base本身;

拓展:

       new Base() == Base () 返回的結果為false

    例如當result為[]的時候,new Base()返回結果和Base()返回結果的都是[],但實際上他們並不相等 , Javascript  對於 Object 和 Function 的比較是基於引用的.

Var m = [],t = []; m == t;//false,並不是同一個引用

Var m = t = []; m == t;//true

b.    jQuery中jQuery.fn為什么表現為數組


 

jQuery將對象模擬成了數組,而如何讓一個對象模擬成數組,jQuery給對象加上了以下幾個屬性:

{
  length: 0,
  push: [].push,
  sort: [].sort,
  splice: [].splice
},

不同的是chrome在給對象添加了length和splice后真的轉化成了數組,如$()結果是[],而ie沒有轉化$()結果是{}。但是無所謂,他們都可以使用length等屬性,不影響后續使用。如果$(…)有搜索結果,jQuery會把結果拼接成數組返回,這樣jQuery的返回結果看起來總是數組。

 

總結


 

  由上面的分析可知jQuery.fn.init.prototype = jQuery.fn目的就是將jQuery.fn上的所有屬性都掛在jQuery實例$(...)上,使得實例擁有很多jQuery.fn上定義的函數。比如jQuery.fn.extend函數,實例就可以直接使用:$(...).extend({"name": "chua"})。

  由於每次都是一個新的實例new jQuery.fn.init(selector,context,rootjQuery),所以各個實例是獨立的。而jQuery全局的屬性直接掛在jQuery上,比如jQuery.extend,這個和jQuery.fn.extend不一樣了,因為jQuery.extend是全局的,比如jQuery.extend({"test": "chua"})你可以隨時通過jQuery.test就把值給取出來了,而jQuery實例則需要保證同一個實例的情況下才能取到值。比如var ps = $("p").extend({"test": "chua"}),通過ps.test能夠取到值,但是你使用$("p").test是取不到的。因為你使用$(...)又新建了一個實例。

  至於jQuery的鏈式調用很好理解,源碼初始化的時候返回了jQuery對象本身:

init: function(selector,context,rootjQuery){
  ...
  return this;
}

  這一節先到這里,待續……

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM