jQuery源碼解讀:部份jQuery工具方法實現

jQuery做爲前端最流行的類庫,沒有之一,源碼必須得讀一讀。本博將不按期更新源碼解讀內容,若是解讀不正確的地方,還請同窗們在評論中指正。前端

本系列文章基於jquery-1.9.1.js。(編者注:雖然JQ已經出到2.X,本文所述的方法是基本方法,沒有版本之差,對於學習有所幫助)jquery

1、$.type() 判斷js數據類型

用法:$.type(new Array()); //array正則表達式

部份源碼(截取關鍵部份,請忽略源碼語法):chrome

//生成typelist的map
class2type = {}
jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
    class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

//每一個對象實例都有toString方法
core_toString = class2type.toString

//主方法
type: function( obj ) {
    if ( obj == null ) {
        return String( obj );
    }
    return typeof obj === "object" || typeof obj === "function" ?
        class2type[ core_toString.call(obj) ] || "object" :
        typeof obj;
}

解讀:數組

一、class2type生成後的內容爲

var class2type = {
    "[object Boolean]":"boolean",
    "[object Number]":"number",
    "[object String]":"string",
    "[object Function]":"function",
    "[object Array]":"array",
    "[object Date]":"date",
    "[object RegExp]":"regexp",
    "[object Object]":"object",
    "[object Error]":"error"
}

二、core_toString使用的是對象實例的toString

全部繼隨自Object的對象都有toString方法,爲何必定要使用object.toString,由於array,function雖然有toString方法,但該方法進行了重寫,array調用toString打印的數組成員用逗號隔開的字符串。這裏使用的是{}.toString.call(obj);改變toString的this指向爲object實例。jquery爲何使用的是class2type.toString.call,這樣就能夠少聲明一個object。ide

var func = function(){};
var arr = [];
console.log({}.toString.call(func)); //[object Function]
console.log({}.toString.call(arr)); //[object Array]

這樣就獲得class2type的鍵名,以此判斷數據類型。函數

2、$.each() 遍歷一個數組或對象。

each()其實仍是使用的for來進行循環的,除了方便外,因其作了一下簡單的封裝,因此效率仍是要比for差,對於大型循環,儘可能使用for.post

3、$.trim() 去除字符串兩端的空格。

rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g
core_version = "1.9.1"
//僅僅是使用字符串的trim方法
core_trim = core_version.trim

//主方法,首先嚐試使用字符串原生的trim方法(非IE支持)
//不支持的話,使用String.prototype.trim.call("\uFEFF\xA0")
//最後使用正則replace
trim: core_trim && !core_trim.call("\uFEFF\xA0") ?
    function( text ) {
        return text == null ?
            "" :
            core_trim.call( text );
    } :

    // 上述兩個方法不支持,使用自定義的方法,清空兩邊的空格或特殊字符
    function( text ) {
        return text == null ?
            "" :
            ( text + "" ).replace( rtrim, "" );
    }

該方法須要解釋的是,「\uFEFF」和「\xA0」。學習

某些軟件,在保存一個以UTF-8編碼的文件時,會在文件開始的地方插入三個不可見的字符(0xEF 0xBB 0xBF,即BOM),轉碼後是「\uFEFF」,所以咱們在讀取時須要本身去掉這些字符。this

「\xA0」其實就是HTML中常見的「&nbsp」

4、$.isNumeric() 判斷是不是數字

isNumeric: function( obj ) {
    return !isNaN( parseFloat(obj) ) && isFinite( obj );
}

isFinite() 函數用於檢查其參數是不是無窮大。若是 number 是有限數字(或可轉換爲有限數字),那麼返回 true。不然,若是 number 是 NaN(非數字),或者是正、負無窮大的數,則返回 false。

5、$.isEmptyObject() 判斷對象是否爲空

isEmptyObject: function( obj ) {
    var name;
    for ( name in obj ) {
        return false;
    }
    return true;
}

這個方法很好懂,就很少解釋

6、$.parseJSON() 將JSON字符串轉換爲JSON對象

// JSON RegExp
rvalidchars = /^[\],:{}\s]*$/,
rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,
rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g

parseJSON: function( data ) {
    // 若是有原生的JSON對象支持,使用原生對象
    if ( window.JSON && window.JSON.parse ) {
        return window.JSON.parse( data );
    }

    if ( data === null ) {
        return data;
    }

    if ( typeof data === "string" ) {

        // 去掉兩端空格,製表符,bom
        data = jQuery.trim( data );

        if ( data ) {
            // 保證輸入的字符串是可用的JSON字符串
            if ( rvalidchars.test( data.replace( rvalidescape, "@" )
                .replace( rvalidtokens, "]" )
                .replace( rvalidbraces, "")) ) {
                console.log(data);
                return ( new Function( "return " + data ) )();
            }
        }
    }

    jQuery.error( "Invalid JSON: " + data );
}

這個方法主要是看上面幾個正則表達式,從字符串轉JSON對象,僅僅是使用return ( new Function( 「return 」 + data ) )();

7、$.globalEval() 在全局做用域執行一段JS腳本

// 在全局做用域執行JS腳本
globalEval: function( data ) {
    if ( data && jQuery.trim( data ) ) {
        // 在IE中使用execScript
        // 由於使用匿名函數,因此做用域使用的是window
        ( window.execScript || function( data ) {
            window[ "eval" ].call( window, data );
        } )( data );
    }
}

jQuery該方法源於:Jim Driscoll

方法原理:eval做用域問題

var a = "window";
function b(){
    eval('var a = "b"');
}
b();
alert(a); //a的結果爲window;IE、chrome、FF結果一致
window.eval和eval不同的地方:

var a = "window";
function b(){
    window.eval('var a = "b"');
}
b();
alert(a); //IE下仍是a的結果仍是window,chrome、FF的a的結果b

via Just Jason's Blog

相關文章
相關標籤/搜索