jQuery源码分析-03扩展工具函数jQuery.extend
// 扩展工具函数 jQuery.extend({ // http://www.w3school.com.cn/jquery/core_noconflict.asp // 释放$的 jQuery 控制权 // 许多 JavaScript 库使用 $ 作为函数或变量名,jQuery 也一样。 // 在 jQuery 中,$ 仅仅是 jQuery 的别名,因此即使不使用 $ 也能保证所有功能性。 // 假如我们需要使用 jQuery 之外的另一 JavaScript 库,我们可以通过调用 $.noConflict() 向该库返回控制权。 // 通过向该方法传递参数 true,我们可以将 $ 和 jQuery 的控制权都交还给另一JavaScript库。 noConflict: function( deep ) { // 交出$的控制权 if ( window.$ === jQuery ) { window.$ = _$; //window.$失效 } // 交出jQuery的控制权 if ( deep && window.jQuery === jQuery ) { window.jQuery = _jQuery; //window.jQuery失效 } return jQuery; }, // Is the DOM ready to be used? Set to true once it occurs. isReady: false, // A counter to track how many items to wait for before // the ready event fires. See #6781 // 一个计数器,用于跟踪在ready事件出发前的等待次数 readyWait: 1, // Hold (or release) the ready event // 继续等待或触发 holdReady: function( hold ) { if ( hold ) { jQuery.readyWait++; } else { jQuery.ready( true ); } }, // Handle when the DOM is ready // 文档加载完毕句柄 // http://www.cnblogs.com/fjzhou/archive/2011/05/31/jquery-source-4.html ready: function( wait ) { // Either a released hold or an DOMready/load event and not yet ready // if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) { // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). // 确保document.body存在 if ( !document.body ) { return setTimeout( jQuery.ready, 1 ); } // Remember that the DOM is ready jQuery.isReady = true; // If a normal DOM Ready event fired, decrement, and wait if need be if ( wait !== true && --jQuery.readyWait > 0 ) { return; } // If there are functions bound, to execute readyList.resolveWith( document, [ jQuery ] ); // Trigger any bound ready events if ( jQuery.fn.trigger ) { jQuery( document ).trigger( "ready" ).unbind( "ready" ); } } }, // 初始化readyList事件处理函数队列 // 兼容不同浏览对绑定事件的区别 bindReady: function() { if ( readyList ) { return; } readyList = jQuery._Deferred(); // Catch cases where $(document).ready() is called after the // browser event has already occurred. if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready return setTimeout( jQuery.ready, 1 ); } // Mozilla, Opera and webkit nightlies currently support this event // 兼容事件,通过检测浏览器的功能特性,而非嗅探浏览器 if ( document.addEventListener ) { // Use the handy event callback // 使用较快的加载完毕事件 document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); // A fallback to window.onload, that will always work // 注册window.onload回调函数 window.addEventListener( "load", jQuery.ready, false ); // If IE event model is used } else if ( document.attachEvent ) { // ensure firing before onload, // maybe late but safe also for iframes // 确保在onload之前触发onreadystatechange,可能慢一些但是对iframes更安全 document.attachEvent( "onreadystatechange", DOMContentLoaded ); // A fallback to window.onload, that will always work // 注册window.onload回调函数 window.attachEvent( "onload", jQuery.ready ); // If IE and not a frame // continually check to see if the document is ready var toplevel = false; try { toplevel = window.frameElement == null; } catch(e) {} if ( document.documentElement.doScroll && toplevel ) { doScrollCheck(); } } }, // See test/unit/core.js for details concerning isFunction. // Since version 1.3, DOM methods and functions like alert // aren't supported. They return false on IE (#2968). // 是否函数 isFunction: function( obj ) { return jQuery.type(obj) === "function"; }, // 是否数组 // 如果浏览器有内置的 Array.isArray 实现,就使用浏览器自身的实现方式, // 否则将对象转为String,看是否为"[object Array]"。 isArray: Array.isArray || function( obj ) { return jQuery.type(obj) === "array"; }, // A crude way of determining if an object is a window // 简单的判断(判断setInterval属性)是否window对象 isWindow: function( obj ) { return obj && typeof obj === "object" && "setInterval" in obj; }, // 是否是保留字NaN isNaN: function( obj ) { // 等于null 或 不是数字 或调用window.isNaN判断 return obj == null || !rdigit.test( obj ) || isNaN( obj ); }, // 获取对象的类型 type: function( obj ) { // 通过核心API创建一个对象,不需要new关键字 // 普通函数不行 // 调用Object.prototype.toString方法,生成 "[object Xxx]"格式的字符串 // class2type[ "[object " + name + "]" ] = name.toLowerCase(); return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, // 检查obj是否是一个纯粹的对象(通过"{}" 或 "new Object"创建的对象) // console.info( $.isPlainObject( {} ) ); // true // console.info( $.isPlainObject( '' ) ); // false // console.info( $.isPlainObject( document.location ) ); // true // console.info( $.isPlainObject( document ) ); // false // console.info( $.isPlainObject( new Date() ) ); // false // console.info( $.isPlainObject( ) ); // false // isPlainObject分析与重构 http://www.jb51.net/article/25047.htm // 对jQuery.isPlainObject()的理解 http://www.cnblogs.com/phpmix/articles/1733599.html isPlainObject: function( obj ) { // Must be an Object. // Because of IE, we also have to check the presence of the constructor property. // Make sure that DOM nodes and window objects don't pass through, as well // 必须是一个对象 // 因为在IE8中会抛出非法指针异常,必须检查constructor属性 // DOM节点和window对象,返回false // obj不存在 或 非object类型 或 DOM节点 或 widnow对象,直接返回false // 测试以下三中可能的情况: // jQuery.type(obj) !== "object" 类型不是object,忽略 // obj.nodeType 认为DOM节点不是纯对象 // jQuery.isWindow( obj ) 认为window不是纯对象 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { return false; } // Not own constructor property must be Object // 测试constructor属性 // 具有构造函数constructor,却不是自身的属性(即通过prototype继承的), if ( obj.constructor && !hasOwn.call(obj, "constructor") && !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } // Own properties are enumerated firstly, so to speed up, // if last one is own, then all properties are own. var key; for ( key in obj ) {} // key === undefined及不存在任何属性,认为是简单的纯对象 // hasOwn.call( obj, key ) 属性key不为空,且属性key的对象自身的(即不是通过prototype继承的) return key === undefined || hasOwn.call( obj, key ); }, // 是否空对象 isEmptyObject: function( obj ) { for ( var name in obj ) { return false; } return true; }, // 抛出一个异常 error: function( msg ) { throw msg; }, // 解析JSON // parseJSON把一个字符串变成JSON对象。 // 我们一般使用的是eval。parseJSON封装了这个操作,但是eval被当作了最后手段。 // 因为最新JavaScript标准中加入了JSON序列化和反序列化的API。 // 如果浏览器支持这个标准,则这两个API是在JS引擎中用Native Code实现的,效率肯定比eval高很多。 // 目前来看,Chrome和Firefox4都支持这个API。 parseJSON: function( data ) { if ( typeof data !== "string" || !data ) { return null; } // Make sure leading/trailing whitespace is removed (IE can't handle it) data = jQuery.trim( data ); // Attempt to parse using the native JSON parser first // 原生JSON API。反序列化是JSON.stringify(object) if ( window.JSON && window.JSON.parse ) { return window.JSON.parse( data ); } // Make sure the incoming data is actual JSON // Logic borrowed from http://json.org/json2.js // ... 大致地检查一下字符串合法性 if ( rvalidchars.test( data.replace( rvalidescape, "@" ) .replace( rvalidtokens, "]" ) .replace( rvalidbraces, "")) ) { return (new Function( "return " + data ))(); } jQuery.error( "Invalid JSON: " + data ); }, // Cross-browser xml parsing // (xml & tmp used internally) // 解析XML 跨浏览器 // parseXML函数也主要是标准API和IE的封装。 // 标准API是DOMParser对象。 // 而IE使用的是Microsoft.XMLDOM的 ActiveXObject对象。 parseXML: function( data , xml , tmp ) { if ( window.DOMParser ) { // Standard 标准XML解析器 tmp = new DOMParser(); xml = tmp.parseFromString( data , "text/xml" ); } else { // IE IE的XML解析器 xml = new ActiveXObject( "Microsoft.XMLDOM" ); xml.async = "false"; xml.loadXML( data ); } tmp = xml.documentElement; if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) { jQuery.error( "Invalid XML: " + data ); } return xml; }, // 无操作函数 noop: function() {}, // Evaluates a script in a global context // Workarounds based on findings by Jim Driscoll // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context // globalEval函数把一段脚本加载到全局context(window)中。 // IE中可以使用window.execScript。 // 其他浏览器 需要使用eval。 // 因为整个jQuery代码都是一整个匿名函数,所以当前context是jQuery,如果要将上下文设置为window则需使用globalEval。 globalEval: function( data ) { // data非空 if ( data && rnotwhite.test( data ) ) { // We use execScript on Internet Explorer // We use an anonymous function so that context is window // rather than jQuery in Firefox ( window.execScript || function( data ) { window[ "eval" ].call( window, data ); } )( data ); } }, // 判断节点名称是否相同 nodeName: function( elem, name ) { // 忽略大小写 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase(); }, // args is for internal usage only // 遍历对象或数组 each: function( object, callback, args ) { var name, i = 0, length = object.length, isObj = length === undefined || jQuery.isFunction( object ); // 如果有参数args,调用apply,上下文设置为当前遍历到的对象,参数使用args if ( args ) { if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } // A special, fast, case for the most common use of each // 没有参数args则调用,则调用call,上下文设置为当前遍历到的对象,参数设置为key/index和value } else { if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object; }, // Use native String.trim function wherever possible // 尽可能的使用本地String.trim方法,否则先过滤开头的空格,再过滤结尾的空格 trim: trim ? function( text ) { return text == null ? "" : trim.call( text ); } : // Otherwise use our own trimming functionality function( text ) { return text == null ? "" : text.toString().replace( trimLeft, "" ).replace( trimRight, "" ); }, // results is for internal usage only // 将伪数组转换为数组 makeArray: function( array, results ) { var ret = results || []; if ( array != null ) { // The window, strings (and functions) also have 'length' // The extra typeof function check is to prevent crashes // in Safari 2 (See: #3039) // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 // 一大堆浏览器兼容性测试,真实蛋疼 var type = jQuery.type( array ); // 测试:有没有length属性、字符串、函数、正则 // 不是数组,连伪数组都不是 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { // $.type( $('div') ) // object jQuery.merge( ret, array ); } } return ret; }, // inArray: function( elem, array ) { // 是否有本地化的Array.prototype.indexOf if ( indexOf ) { // 直接调用Array.prototype.indexOf return indexOf.call( array, elem ); } // 遍历数组,查找是否有完全相等的元素,并返回下标 // 循环的小技巧:把array.length存放到length变量中,可以减少一次作用域查找 for ( var i = 0, length = array.length; i < length; i++ ) { if ( array[ i ] === elem ) { return i; } } // 如果返回-1,则表示不在数组中 return -1; }, // 将数组second合并到数组first中 merge: function( first, second ) { var i = first.length, // j = 0; // 如果second的length属性是Number类型,则把second当数组处理 if ( typeof second.length === "number" ) { for ( var l = second.length; j < l; j++ ) { first[ i++ ] = second[ j ]; } } else { // 遍历second,将非undefined的值添加到first中 while ( second[j] !== undefined ) { first[ i++ ] = second[ j++ ]; } } // 修正first的length属性,因为first可能不是真正的数组 first.length = i; return first; }, // 过滤数组,返回新数组;callback返回true时保留;如果inv为true,callback返回false才会保留 grep: function( elems, callback, inv ) { var ret = [], retVal; inv = !!inv; // Go through the array, only saving the items // that pass the validator function // 遍历数组,只保留通过验证函数callback的元素 for ( var i = 0, length = elems.length; i < length; i++ ) { // 这里callback的参数列表为:value, index,与each的习惯一致 retVal = !!callback( elems[ i ], i ); // 是否反向选择 if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret; }, // arg is for internal usage only // 将数组或对象elems的元素/属性,转化成新的数组 map: function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, // jquery objects are treated as arrays // 检测elems是否是(伪)数组 // 1. 将jQuery对象也当成数组处理 // 2. 检测length属性是否存在,length等于0,或第一个和最后一个元素是否存在,或jQuery.isArray返回true isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // 是数组或对象的差别,仅仅是遍历的方式不同,没有其他的区别 // Go through the array, translating each of the items to their // 遍历数组,对每一个元素调用callback,将返回值不为null的值,存入ret if ( isArray ) { for ( ; i < length; i++ ) { // 执行callback,参数依次为value, index, arg value = callback( elems[ i ], i, arg ); // 如果返回null,则忽略(无返回值的function会返回undefined) if ( value != null ) { ret[ ret.length ] = value; } } // Go through every key on the object, // 遍历对象,对每一个属性调用callback,将返回值不为null的值,存入ret } else { for ( key in elems ) { // 执行callback,参数依次为value, key, arg value = callback( elems[ key ], key, arg ); // 同上 if ( value != null ) { ret[ ret.length ] = value; } } } // Flatten any nested arrays // 使嵌套数组变平 // concat: // 如果某一项为数组,那么添加其内容到末尾。 // 如果该项目不是数组,就将其作为单个的数组元素添加到数组的末尾。 return ret.concat.apply( [], ret ); }, // A global GUID counter for objects guid: 1, // Bind a function to a context, optionally partially applying any // arguments. // 代理方法:为fn指定上下文(即this) // jQuery.proxy( function, context ) // jQuery.proxy( context, name ) proxy: function( fn, context ) { // 如果context是字符串,设置上下文为fn,fn为fn[ context ] // 即设置fn的context方法的上下文为fn(默认不是这样吗???TODO) if ( typeof context === "string" ) { var tmp = fn[ context ]; context = fn; fn = tmp; } // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. // 快速测试fn是否是可调用的(即函数),在文档说明中,会抛出一个TypeError, // 但是这里仅返回undefined if ( !jQuery.isFunction( fn ) ) { return undefined; } // Simulated bind var args = slice.call( arguments, 2 ), // 从参数列表中去掉fn,context proxy = function() { // 设置上下文为context和参数 return fn.apply( context, args.concat( slice.call( arguments ) ) ); }; // Set the guid of unique handler to the same of original handler, so it can be removed // 统一guid,使得proxy能够被移除 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++; return proxy; }, // Mutifunctional method to get and set values to a collection // The value/s can be optionally by executed if its a function // 多功能函数,读取或设置集合的属性值;值为函数时会被执行 // fn:jQuery.fn.css, jQuery.fn.attr, jQuery.fn.prop access: function( elems, key, value, exec, fn, pass ) { var length = elems.length; // Setting many attributes // 如果有多个属性,则迭代 if ( typeof key === "object" ) { for ( var k in key ) { jQuery.access( elems, k, key[k], exec, fn, value ); } return elems; } // Setting one attribute // 只设置一个属性 if ( value !== undefined ) { // Optionally, function values get executed if exec is true exec = !pass && exec && jQuery.isFunction(value); for ( var i = 0; i < length; i++ ) { fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); } return elems; } // Getting an attribute // 读取属性 return length ? fn( elems[0], key ) : undefined; }, // 获取当前时间的便捷函数 now: function() { return (new Date()).getTime(); }, // Use of jQuery.browser is frowned upon. // More details: http://docs.jquery.com/Utilities/jQuery.browser // 不赞成使用jQuery.browser,推荐使用jQuery.support // Navigator 正在使用的浏览器的信息 // Navigator.userAgent 一个只读的字符串,声明了浏览器用于HTPP请求的用户代理头的值 uaMatch: function( ua ) { ua = ua.toLowerCase(); // 依次匹配各浏览器 var match = rwebkit.exec( ua ) || ropera.exec( ua ) || rmsie.exec( ua ) || ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) || []; // match[1] || "" // match[1]为false(空字符串、null、undefined、0等)时,默认为"" // match[2] || "0" // match[2]为false(空字符串、null、undefined、0等)时,默认为"0" return { browser: match[1] || "", version: match[2] || "0" }; }, // 创建一个新的jQuery副本,副本的属性和方法可以被改变,但是不会影响原始的jQuery对象 // 有两种用法: // 1. 覆盖jQuery的方法,而不破坏原始的方法 // 2.封装,避免命名空间冲突,可以用来开发jQuery插件 // 值得注意的是,jQuery.sub()函数并不提供真正的隔离,所有的属性、方法依然指向原始的jQuery // 如果使用这个方法来开发插件,建议优先考虑jQuery UI widget工程 sub: function() { function jQuerySub( selector, context ) { return new jQuerySub.fn.init( selector, context ); } jQuery.extend( true, jQuerySub, this ); // 深度拷贝,将jQuery的所有属性和方法拷贝到jQuerySub jQuerySub.superclass = this; jQuerySub.fn = jQuerySub.prototype = this(); // jQuerySub.fn.constructor = jQuerySub; jQuerySub.sub = this.sub; jQuerySub.fn.init = function init( selector, context ) { if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { context = jQuerySub( context ); } return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); }; jQuerySub.fn.init.prototype = jQuerySub.fn; var rootjQuerySub = jQuerySub(document); return jQuerySub; }, // 浏览器类型和版本: // $.browser.msie/mozilla/webkit/opera // $.browser.version // 不推荐嗅探浏览器类型jQuery.browser,而是检查浏览器的功能特性jQuery.support // 未来jQuery.browser可能会移到一个插件中 browser: {} });
详细分析:
$.noConflict() 方法释放变量 $ 的 jQuery 控制权。
该方法也可用于为 jQuery 变量规定新的自定义名称。
提示:在其他 JavaScript 库为其函数使用 $ 时,该方法很有用。
如:调用noConflict("deep") var jq = $.noConflict("deep"); jQuery(".bg").hide(); //jQuery失效,无deep,,则$失效
$.holdReady() 函数用于暂停或恢复.ready() 事件的执行。
注意:
1. 该方法必须在文档靠前部分被调用,例如,在头部加载完 jQuery 脚本之后,立刻调用该方法。如果在 ready 事件已经被调用后再调用该方法,将不会起作用。
2. 首先调用$.holdReady(true)[调用后 ready 事件将被锁定]。当准备好执行 ready 事件时,调用$.holdReady(false)。
3. 可以对 ready 事件添加多个锁定,每个锁定对应一次$.holdReady(false)[解锁]调用。ready 事件将在所有的锁定都被解除,并且页面也已经准备好的情况下被触发。
$.holdReady(true) $(document).ready(function(){ $("#first").click(function(){ alert("解除延迟后被弹出"); }) }) $("#second").click(function(){ $.holdReady(false); })
另外,执行$.holdReady(true)后,holdReady++;
$.ready 使函数在文档加载后是可用的: 定义和用法: 当 DOM(document object model 文档对象模型)加载完毕且页面完全加载(包括图像)时发生 ready 事件。 由于该事件在文档就绪后发生,因此把所有其他的 jQuery 事件和函数置于该事件中是非常好的做法。如上面的实例所示。 ready() 方法规定当 ready 事件发生时执行的代码。 提示:ready() 方法不应该与 <body onload=""> 一起使用。 语法: 允许使用以下两种语法: $(document).ready(function) ready() 方法只能用于当前文档,因此无需选择器: $(function)
$.bindReady()兼容多浏览器
if ( document.addEventListener ) {
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
window.addEventListener( "load", jQuery.ready, false );
} else if ( document.attachEvent ) {
document.attachEvent( "onreadystatechange", DOMContentLoaded );
// 确保在onload之前触发onreadystatechange,可能慢一些但是对iframes更安全
window.attachEvent( "onload", jQuery.ready );
}
$.type检查类型 type: function( obj ) { // 调用Object.prototype.toString方法,生成 "[object Xxx]"格式的字符串 // class2type[ "[object " + name + "]" ] = name.toLowerCase(); return obj == null ? String( obj ) : class2type[ toString.call(obj) ] || "object"; }, // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { class2type[ "[object " + name + "]" ] = name.toLowerCase(); });
$.parseJSON() 函数用于将符合标准格式的的JSON字符串转为与之对应的JavaScript对象。 var obj = jQuery.parseJSON('{"name":"John"}'); $.parseJSON() 函数用于将符合标准格式的的JSON字符串转为与之对应的JavaScript对象。 注意:传入格式有误的 JSON 字符串可能导致抛出异常。例如,下面这些无效的 JSON 字符串: "{test: 1}" //test是属性名称,必须加双引号 "{'test': 1}" //test是属性名称,必须用双引号(不能用单引号) "'test'" //test是属性名称,必须用双引号(不能用单引号) ".1" //number 必须以数字开头; "0.1" 将是有效的 "undefined" //undefined 不能表示一个 JSON 字符串; null可以 "NaN" //NaN 不能表示一个 JSON 字符串; 用Infinity直接表示无限也是不允许的 JSON标准不允许"控制字符"如制表符或换行符,例如: // 多数情况下,它会抛出一个错误,因为JS解析器会将字符串中的\t或\n等转义直接视作字面值,起到Tab或换行的效果。 $.parseJSON('{"testing":"1\t2\n3"}') 正确写法应该如下(使用两个反斜杠,以免被JS解析器直接转义\t或\n): $.parseJSON('{"testing":"1\\t2\\n3"}') 注意:在jQuery 1.9之前(不含1.9):如果传入一个空字符串、null或undefined,该函数将返回null,而不是抛出一个错误,即使它不是有效的JSON字符串。
// 原生JSON API。反序列化是JSON.stringify(object)
if ( window.JSON && window.JSON.parse ) {
return window.JSON.parse( data );
}
$.parseXML() 函数用于将字符串解析为对应的XML文档。 提示:该函数将使用浏览器内置的解析函数来创建一个有效的XML文档,该文档可以传入jQuery()函数来创建一个典型的jQuery对象,从而对其进行遍历或其他操作。
$.globalEval
var name = "全局变量"; $(function () { function test(){ var name = "局部变量"; alert(name); // 局部变量 eval( "alert(name);" ); // 局部变量 $.globalEval( "alert(name);" ); // 全局变量 } test(); })
$.nodeName nodeName 属性可依据节点的类型返回其名称。 如果节点是一个元素节点 , nodeName 属性将返回标签名。 如果节点是一个属性节点, nodeName 属性将返回属性名。 其他节点类型, nodeName 属性将返根据不同的节点类型返回不同的节点名称。
$.makeArray var elems = document.getElementsByTagName("div"); // 返回一个节点列表 var arr = jQuery.makeArray(elems); arr.reverse(); //对列表的元素使用一个数组方法 $(arr).appendTo(document.body);
$.grep var arr = [ 1, 9, 3, 8, 6, 1, 5, 9, 4, 7, 3, 8, 6, 9, 1 ]; $( "div" ).text( arr.join( ", " ) ); arr = jQuery.grep(arr, function( n, i ) { return ( n !== 5 && i > 4 ); }); $( "p" ).text( arr.join( ", " ) ); arr = jQuery.grep(arr, function( a ) { return a !== 9; }); $( "span" ).text( arr.join( ", " ) );
$.proxy 强制执行 objPerson 内的 "test" 函数的上下文: var objPerson = { name: "John Doe", age: 32, test: function(){ $("p").after("Name: " + this.name + "<br> Age: " + this.age); } }; $("button").click($.proxy(objPerson,"test"));
$.sub
添加一个方法到jQuery sub,以便它不会暴露在外 (function(){ var sub = jQuery.sub(); sub.fn.myCustomMethod = function(){ return 'just for me'; }; sub(document).ready(function() { alert(sub('body').myCustomMethod()); }); alert(typeof jQuery('body').myCustomMethod); //underfine })(); $.sub() 函数可创建一个新的jQuery副本,其属性和方法可以修改,而不会影响原来的jQuery对象。
jQuery源码分析-03扩展工具函数jQuery.extend的更多相关文章
- jQuery 源码分析 8: 回头看jQuery的构造器(jQuery.fn,jQury.prototype,jQuery.fn.init.prototype的分析)
在第一篇jQuery源码分析中,简单分析了jQuery对象的构造过程,里面提到了jQuery.fn.jQuery.prototype.jQuery.fn.init.prototype的关系. 从代码中 ...
- 【转】jQuery源码分析-03构造jQuery对象-源码结构和核心函数
作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com 毕竟是边读边写,不对的地方请告诉我,多多交流共同进步.本章还未写完,完了会提交PDF. 前记: 想系 ...
- jQuery源码分析-03构造jQuery对象-源码结构和核心函数
3. 构造jQuery对象 3.1源码结构 先看看总体结构,再做分解: (function( window, undefined ) { var jQuery = (function() { // 构 ...
- jquery 源码学习(四)构造jQuery对象-工具函数
jQuery源码分析-03构造jQuery对象-工具函数,需要的朋友可以参考下. 作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com 声明:本文为原 ...
- jQuery源码分析系列
声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://git ...
- [转]jQuery源码分析系列
文章转自:jQuery源码分析系列-Aaron 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAaro ...
- jQuery源码分析系列(转载来源Aaron.)
声明:非本文原创文章,转载来源原文链接Aaron. 版本截止到2013.8.24 jQuery官方发布最新的的2.0.3为准 附上每一章的源码注释分析 :https://github.com/JsAa ...
- jQuery源码分析系列——来自Aaron
jQuery源码分析系列——来自Aaron 转载地址:http://www.cnblogs.com/aaronjs/p/3279314.html 版本截止到2013.8.24 jQuery官方发布最新 ...
- jQuery源码分析-each函数
本文部分截取自且行且思 jQuery.each方法用于遍历一个数组或对象,并对当前遍历的元素进行处理,在jQuery使用的频率非常大,下面就这个函数做了详细讲解: 复制代码代码 /*! * jQuer ...
随机推荐
- css3特效详解
好吧,CSS3 3D transform变换,不过如此! 这篇文章发布于 2012年09月7日,星期五,01:05,归类于 css相关. 阅读 408042 次, 今日 34 次 一.写在前面的秋裤 ...
- 谈谈java中遍历Map的几种方法
java中的map遍历有多种方法,从最早的Iterator,到java5支持的foreach,再到java8 Lambda,让我们一起来看下具体的用法以及各自的优缺点 先初始化一个map public ...
- 【WPF】DispatcherFrame 是个啥玩意儿
对于 WPF 的线程模型,Dispatcher 对象相信各位大伙伴已经不陌生,尤其是跨线程更新UI的时候,都会用它来调度消息.与 Dispatcher 对象有关的,还有一个叫 DispatcherFr ...
- CoolBlog开发笔记第4课:数据库模型设计
教程目录 1.1 CoolBlog开发笔记第1课:项目分析 1.2 CoolBlog开发笔记第2课:搭建开发环境 1.3 CoolBlog开发笔记第3课:创建Django应用 前言 我新书<Py ...
- Linux: Bash基本命令
切换目录 cd 查看当前目录 pwd 生成目录 mkdir 搜索文件 查看当前的文件 ls 删除文件但保留特定类型 rm !(**) 例如: rm !(.tex|*.eps)其中,.tex, .eps ...
- 【Android Developers Training】 56. 更效率地加载大图片
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- JS中创建自定义对象的方法
1.直接给对象扩充属性和方法: 2.对象字面量: 3.工厂方式: 4.构造函数方式: 5.原型方式: 6.混合方式. <script> // 1.直接给对象扩充属性和方法; var cat ...
- 【CC2530入门教程-06】CC2530的ADC工作原理与应用
第6课 CC2530的ADC工作原理与应用 广东职业技术学院 欧浩源 一.A/D转换的基本工作原理 将时间上连续变化的模拟量转化为脉冲有无的数字量,这一过程就叫做数字化,实现数字化的关键设备是AD ...
- app 选项卡代码
<div id="segmented" class="mui-segmented-control"> <a class="mui-c ...
- JAVA基础——异常详解
JAVA异常与异常处理详解 一.异常简介 什么是异常? 异常就是有异于常态,和正常情况不一样,有错误出错.在java中,阻止当前方法或作用域的情况,称之为异常. java中异常的体系是怎么样的呢? 1 ...