jQuery做爲前端最流行的類庫,沒有之一,源碼必須得讀一讀。本博將不按期更新源碼解讀內容,若是解讀不正確的地方,還請同窗們在評論中指正。前端
本系列文章基於jquery-1.9.1.js。(編者注:雖然JQ已經出到2.X,本文所述的方法是基本方法,沒有版本之差,對於學習有所幫助)jquery
用法:$.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; }
解讀:數組
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" }
全部繼隨自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的鍵名,以此判斷數據類型。函數
each()其實仍是使用的for來進行循環的,除了方便外,因其作了一下簡單的封裝,因此效率仍是要比for差,對於大型循環,儘可能使用for.post
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中常見的「 」
isNumeric: function( obj ) { return !isNaN( parseFloat(obj) ) && isFinite( obj ); }
isFinite() 函數用於檢查其參數是不是無窮大。若是 number 是有限數字(或可轉換爲有限數字),那麼返回 true。不然,若是 number 是 NaN(非數字),或者是正、負無窮大的數,則返回 false。
isEmptyObject: function( obj ) { var name; for ( name in obj ) { return false; } return true; }
這個方法很好懂,就很少解釋
// 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 ) )();
// 在全局做用域執行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