jQuery 源碼分析和使用心得 - core.js


  core是jQuery的核心內容, 包含了最基礎的方法, 比如我們常用的 $(selector, context), 用於遍歷操作的 each, map, eq, first 識別變量類型的 isArray, isNumeric, type 等 . 這些方法為jQuery后續操作提供最基礎的支持. 

構造函數 jQuery( selector, context )

  說到jQuery, 大家可能最熟悉的就是 $(selector, context) , 我覺得這也是jQuery受到人們歡迎的很大一部分原因, 因為這個方法非常的強大.

    // Define a local copy of jQuery
    jQuery = function( selector, context ) {
        // The jQuery object is actually just the init constructor 'enhanced'
        // Need init if jQuery is called (just allow error to be thrown if not included)
        return new jQuery.fn.init( selector, context );
    },

  這里我們很明顯的看到一個關鍵詞就是new ,這說明每一次調用$()就會new一個jQuery對象出來 , 有些人可能不注意這一點就會寫出下面的代碼, 或者會出現 $("#id") === $("#id")的這種判斷 , 這種寫法都是不可取的, 我們應該盡量的節省jQuery的獲取次數, 重復利用jQuery對象.

if($(".class").hasClass()){
    $(".class").removeClass();
}

靜態屬性和原型屬性

  從core.js中可以看到兩類屬性( q君: 函數也是屬性哦! ), 一類是以jQuery.extend({})定義的靜態屬性, 一類是通過  jQuery.fn = jQuery.prototype = {} 進行定義的原型屬性. 靜態屬性是jQuery函數的屬性, 通過 $調用, 如$.each . 靜態屬性通常為與頁面元素無關的工具方法. 原型屬性是拓展jQuery對象的一些功能, 它持有jQuery對象自身(this) , 為處理自身對象之用 調用形式為  var $a = $("a"); $a.each() .( q君: jQuery里面有兩個each ,要分清 )  

  具體的實現方法都比較簡單, 就不再一一敘述. jQuery.extend 是一個很常用的方法, 它可以將幾個對象合並成一個對象, 並且支持深拷貝和淺拷貝兩種方式 , 在做一些默認配置和實現的時候會經常用到.  

jQuery對象創建

  通過查看 jQuery( selector, context )函數, 知道了 jQuery 調用了 new jQuery.fn.init( selector, context ). 在這句話上面有一條注釋: Need init if jQuery is called .  我們在 /src/core/目錄下找到init.js. 內容大致如下

init = jQuery.fn.init = function( selector, context ) {
    //  ...
    //  ...
    return this;
    // ...
    retrun this.constructor( context ).find( selector );
    // ...
    return ( context || rootjQuery ).find( selector );
    // ...
    return typeof rootjQuery.ready !== "undefined" ?
                rootjQuery.ready( selector ) :
                // Execute immediately if ready is not present
                selector( jQuery );
    // ...
    return jQuery.makeArray( selector, this );
    
}

// Give the init function the jQuery prototype for later instantiation
init.prototype = jQuery.fn;

  在這個方法里有很多種返回.

    第一種 this, 返回的是init的對象;

    第二種 jquery對象.find(); -> /src/traversing/findFilter.js : find -> return this.pushStack -> return jQuery.merge( this.constructor(), elems ); -> jQuery對象

    第三種 selector(jQuery); 不一定返回jQuery對象

    第四種 rootjQuery.ready( selector ); -> /src/core/ready.js : ready -> return this(rootjQuery) -> jQuery對象

    第五種 jQuery.makeArray( selector, this ); -> var ret = results; return ret; -> jQuery對象

  通過上述觀察, 發現jQuery方法只有一種情況下返回的不是jQuery對象: 傳入的selector參數為對象, 並且沒有加載 /src/core/ready.js 模塊. 下面這段代碼也會證明這種情況(代碼會在附件中, 請及時更新). 

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8">
        <title>core</title>
    </head>

    <body>
        <script src="require.js" data-main="main" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript" charset="utf-8">
            require(['../src/core/init'], function(init) {
                var ret = new init(function() {
                    return {
                        name: "not jquery"
                    };
                });
                console.log(ret);
            })
        </script>
    </body>

</html>

  再來看第一種情況, return this返回的是init對象, 並不是jQuery對象, 但是我們在下面看到 init.prototype = jQuery.fn; 所以通過init創建的對象也就是jQuery對象. 

jQuery實現偽數組

  我們在用jQuery的過程中很多情況下會把jQuery當做數組去用. 但是我們從上面創建過程來看, jQuery貌似跟數組並沒有什么關系. 那么我們來分析一下他的原型看看為什么jQuery可以像數組一樣使用. 

  在這之前我先介紹一下"鴨子類型(duck typing)" ( q君: 鴨子? 好吃嗎? ), 什么是鴨子類型? “當看到一只鳥走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那么這只鳥就可以被稱為鴨子。” 這是一個非常恰當的描述, 在動態語言中我們不需要管一個對象到底是什么類型, 只要他能執行某個方法, 那么我就可以認為他就是某個類型的對象. 

  Javascript就是這樣的一種語言. 要實現數組不一定要繼承或者使用Array對象. 只要實現了Array對象里面的方法, 就可以認為他是數組. 這里我也發現一個很有趣的事情. 用chrome瀏覽器進行調試的時候, 我們用console.log輸出普通對象和數組的時候輸出的格式不一樣. 輸出對象類似於 " f {length: 0} " , 輸出數組類似於 " [1] ". 我們通過下面幾行代碼做個試驗

var f = function(){this.length = 1; this[0] = "a" }
console.log(new f());   //  f {0: "a", length: 1}
var f = function(){this.length = 1;this.splice = function(){};this[0] = "a" }
console.log(new f());   //  ["a"]

  哈, 多么神奇! chrome把他當成數組了! 如果一個對象中length為數字, splice為方法, 這個對象就會被chrome認為是數組. 大家感興趣的話可以試一下其他的瀏覽器. 

  嗯, 我們回過頭看jQuery的prototype, jQuery的prototype中包含了數組中常用的 length屬性, push , sort , splice , slice等方法. 

  所有jQuery就像一個數組一樣使用.

使用建議

  1. 盡量減少重復使用 $()方法獲取相同的對象

  2. $() 大部分會返回jQuery對象, 但不排除在極端情況

  3. jQuery可以當做數組使用, 但不完全是數組, pop, shift 等方法不適用於jQuery對象.

附件

  http://yunpan.cn/Q7nKEsZ9cqFby  提取碼 3a4a

 


免責聲明!

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



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