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