[原创] jQuery源码分析-03构造jQuery对象-工具函数
作者:nuysoft/高云 QQ:47214707 EMail:nuysoft@gmail.com
声明:本文为原创文章,如需转载,请注明来源并保留原文链接。
?
?
读读写写,不对的地方请告诉我,多多交流共同进步,本章的的PDF等本章写完了发布。
?
jQuery源码分析系列的目录请查看?http://nuysoft.iteye.com/blog/1177451,想系统的好好写写,目前还是从我感兴趣的部分开始,如果大家有对哪个模块感兴趣的,建议优先分析的,可以告诉我,一起学习。
?
3.4???????其他静态工具函数// 扩展工具函数
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.$ = _$;
?????? }
?????? // 交出jQuery的控制权
?????? if ( deep && window.jQuery === jQuery ) {
?????????? window.jQuery = _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: {}
//merge方法我觉得可以简化merge:function( first, second ) { var j = 0; while ( second[j]) { first[first.length] = second[ j++ ]; } return first; };//PS:Array.concat();不就可以完成数组的合并吗 2 楼 caniggia1986 2011-12-14 不对Array.concat()只能是数组间合并,first可能是jQuery类型的伪数组 3 楼 caniggia1986 2011-12-14 grep时的inv=!!inv;不错的用法,这样即使不传inv参数默认为false 4 楼 nuysoft 2011-12-14 caniggia1986 写道grep时的inv=!!inv;不错的用法,这样即使不传inv参数默认为false
很实用的技巧 5 楼 王向众 2012-03-30 jquery里面好多技巧啊,我想在基础知识掌握的差不多之后,自己的编程水平就体现在这些技巧上了吧。有的技巧可以代替好多行代码吧,有的技巧还能达到一些难以想到的效果。。。