• jQuery源代码阅读之二——jQuery静态属性和方法


    重点掌握以下这些方法(可以手写代码):

    1.深复制与浅复制 

    jQuery.extend

    2.类型判断相关方法

    jQuery.type,jQuery.isFunction,jQuery.isArray,jQuery.isWindow,jQuery.isNumberic,jQuery.isPlainObject,jQuery.isArrayLike

    3.数组相关方法

    jQuery.each,jQuery.map,jQuery.grep

    4.转驼峰的实现

    jQuery.camelCase

    一、jQuery.extend/jQuery.fn.extend 

        //可接受的参数类型如下:jQuery.extend([deep],target,object1,[objectN])
        jQuery.extend = jQuery.fn.extend = function() {
            var target = arguments[0] || {}, //指向目标对象
                deep = false, //是否进行深度复制
                i = 1, //表示源对象的起始下标
                length = arguments.length, //表示参数个数;
                options, name, src, copy, copyIsArray; //options指向某个源对象,name指向源对象的某个属性名,src目标对象某个属性的原始值,copy某个源对象的某个属性的值,copyIsArray指示变量copy是否为数组        
            //首先进行参数修正
            if (typeof target === 'boolean') {
                deep = target;
                target = arguments[1] || {};
                i = 2;
            }
            //此时target就是jQuery或jQuery.fn
            if (i === length) {
                target = this;
                i--;
            }
            //处理target是字符串或者其他情形,这在深度复制中可能出现
            // if(typeof target!=='object'||!jQuery.isFunction(target)){
            //     target={};
            // }
            for (i; i < length; i++) {
                options = arguments[i];
                for (name in options) {
                    src = target[name];
                    copy = options[name];
                    if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)))) {
                        if (copyIsArray) {
                            copyIsArray = false;
                            clone = src && jQuery.isArray(src) ? src : [];
                        } else {
                            clone = src && jQuery.isPlainObject(src) ? src : {};
                        }
                        //递归调用
                        target[name] = jQuery.extend(deep, clone, copy);
                    } else {
                        target[name] = copy;
                    }
                }
            }
            return target;
        };
    jQuery.extend

    二、jQuery静态方法和属性

    大部分jQuery静态方法为实例方法提供底层支持,相关代码结构如下:

        jQuery.extend({
            //一堆静态方法和属性
            expando:'...',
            noConflict:function(deep){},
            isReady:false,
            readyWait:1,
            holdReady:function(hold){},
            ready:function(){},
            isFunction:function(obj){},
            isArray:Array.isArray,
            isWindow:function(obj){},
            isNumeric:function(obj){},
            type:function(obj){},
            isPlainObject:function(obj){},
            isEmptyObject:function(obj){},
            error:function(msg){},
            parseHTML: function( data, context, keepScripts ){},
            parseJSON:JSON.parse,
            parseCML:function(data){},
            noop:function(){},
            globalEval:function(data){},
            camelCase:function(string){},
            nodeName:function(elem,name){},
            each:function(object,callback,args){},
            trim:function(string){},
            makeArray:function(array,results){},
            inArray:function(elem,array,i){},
            merge:function(first,second){},
            grep:function(elems,callback,inv){},
            map:function(elems,classback,arg){},
            guid:1,
            proxy:function(fn,context){},
            access: function( elems, fn, key, value, chainable, emptyGet, raw ),
            now:Date.now,
            swap: function( elem, options, callback, args ),
        });

    下面逐一对上述方法的实现进行介绍,方法的作用,实现原理不少都在源代码的注释中,请展开来看。

    2.1 jQuery.expando

    expando:'jQuery'+(core_version+Math.random()).replace(/D/g,''),

    2.2 jQuery.noConflict

    在变量区域定义:

            _jQuery=window.jQuery,
            _$=window.$,
            noConflict:function(deep){
                if(window.$===jQuery){
                    window.$=_$;
                }
                if(deep&&window.jQuery===jQuery){
                    window.jQuery=_jQuery;
                }
                return jQuery;
            },
    jQuery.noCoflict实现

    2.3 (todo)ready事件相关静态方法

       JQuery.isReady,jQuery.readyWait;jQuery.holdReady;jQuery.ready 这几个静态方法与事件相关,暂且略过

    2.4 类型判断相关静态方法,

      包括jQuery.isFunction,jQuery.isArray,jQuery.isWindow,jQuery.isNumeric,jQuery.type.这里方法的底层大部分都基于jQuery.type实现.

      具体实现如下

          /****下面是一系列类型检测的静态方法*******/
            isFunction:function(obj){
                //如果使用typeof,在有些浏览器中,正则也会返回function,因此这里采用jQuery处理后的方法,jQuery.type
                return jQuery.type(obj)==='function';
            },
            isArray:Array.isArray,
            isWindow:function(obj){
                return obj!==null&&obj===obj.window;
            },
            //判断obj是否为数字或者数字类型的字符串,并且是有效数字
            isNumeric:function(obj){
                return !isNaN(parseFloat(obj))&&isFinite(obj);
            },
    类型判断相关方法
       // 每个对象都有一个toString()方法,当该对象被表示为一个文本值时,或者一个对象以预期的字符串方式引用时自动调用。默认情况下,toString()方法被每个Object对象继承。
      // 如果此方法在自定义对象中未被覆盖,toString() 返回 "[object type]",其中type是对象的类型。
      type:function(obj){
    if(obj===null){ return String(null); } //Date,Array等类型typeof都会返回object,function、正则(部分浏览器)中 typeof都会返回function if(typeof obj==='object'||typeof obj==='function'){ return class2type[core_toString.call(obj)]; } return typeof obj; },

    其中在变量区域定义class2type

            class2type={},

    并为之赋值

        //目前,js中typeof的返回值有六种:"number," "string," "boolean," "object," "function," 和 "undefined."
        //通过object.prototype.toString/或者{}.toString 返回值有九种:Boolean Number String Function Array Date RegExp Object Error,其中的Array,Date,RegExp,Object,Error都属于Object类型,在有些浏览器中typeof 正则会返回function
        jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(i,name){
            class2type["[object "+name+"]"]=name.toLowerCase();
        });

    2.4 jQuery对象判断相关方法

      jQuery.isPlainObject,jQuery.isEmptyObject

      jQuery.isPlainObject判断的原理,在于判断一些特定的方法,比如isPrototypeOf,hasOwnProperty,是否位于对象自身的原型,而非继承得到的原型链中

            isPlainObject:function(obj){
                if(jQuery.type(obj)!=='object'||obj.nodeType||jQuery.isWindow(obj)){
                    return false;
                }
    
                //如果是纯粹的对象,那么obj一定有constructor属性,并且方法hasOwnPropertyOf一定就在构造函数本身的原型中,而不用通过原型链查找得到
               if(obj.constructor&&!core_hasOwn.call(obj.constructor.prototype,'isPrototypeOf')){
                    return false;
               }
               return true;
    
            },
            //检查是否是空对象
            isEmptyObject:function(obj){
                for(var name in obj){
                    return false;
                }
                return true;
            },
    jQuery对象判断相关方法

    2.5 jQuery数组遍历相关方法

      jQuery.each;jQuery.grep;jQuery.map

    each:function(object,callback,args){
                var i,
                    value, 
                    length=object.length,
                    isArray=isArrayLike(object);
    
                if(args){//说明是内部调用
                    if(isArray){
                        for(i=0;i<length;i++){
                           value= callback.call(object[i],args);
                           if(value===false){
                                break;
                           }
                        }
                    }else{
                        for(i in object){
                            value=callback.call(object[i],args);
                            if(value===false){
                                break;
                            }
                        }
                    }
                }else{
                    if(isArray){
                        for(i=0;i<length;i++){
                            value=callback.call(object[i],i,object[i]);
                            if(value===false){
                                break;
                            }
                        }
                    }else{
                        for(i in object){
                            value=callback.call(object[i],i,object[i]);
                            if(value===false){
                                break;
                            }
                        }
                    }
                }
                return object;
            },
     //用于查找数组中满足过滤函数的元素,形成新的数组之后返回,原数组不受影响
            //如果inv未传入或者是false,元素只有在过滤函数返回true时,才会被保存在最终的结果数组中
            //如果参数inv是true,则恰好相反
            grep:function(elems,callback,inv){
                var i,
                    ret=[],
                    length=elems.length,
                    retVal;
                inv=!!inv;
                for(i=0;i<length;i++){
                    retVal=!!callback.call(elems[i],i);
                    if(retVal!==inv){
                        ret.push(elems[i]);
                    }
                }
                return ret;             
            },
            //用于对数组中每个元素执行callback操作,并将结果形成新的数组返回
            //参数arg仅仅是jQuery内部使用
            map:function(elems,callback,arg){
                var ret=[],
                    retVal,
                    i,
                    length=elems.length,
                    isArray=isArrayLike(elems);
                if(isArray){
                    for(i=0;i<length;i++){
                        retVal=callback.call(elems[i],i,arg);
                        if(retVal!=null){
                            ret.push(retVal);
                        }
                    }
                }else{
                    for(i in elems){
                        retVal=callback.call(elems[i],i,arg);
                        if(retVal!=null){
                            ret.push(retVal);
                        }
                    }
                }
                //保证最终返回的是一维数组
                return core_concat.call([],ret);
            },
    jQuery数组遍历相关方法

    2.6 jQuery.error

            error:function(msg){
                throw new Error(msg);
            },
    jQuery.error

    2.7(todo) jQuery.parseHTML,jQuery.parseJSON,jQuery.parseXML

     parseHTML: function( data, context, keepScripts ){
    
            },
            parseJSON:JSON.parse,
            parseXML:function(data){
                var xml, tmp;
                if ( !data || typeof data !== "string" ) {
                    return null;
                }
    
                // Support: IE9
                try {
                    tmp = new DOMParser();
                    xml = tmp.parseFromString( data , "text/xml" );
                } catch ( e ) {
                    xml = undefined;
                }
    
                if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
                    jQuery.error( "Invalid XML: " + data );
                }
                return xml;
            },
    jQuery.parseHTML,jQuery.parseJSON,jQuery.parseXML

    2.8 jQuery.noop,(todo)jQuery.globalEval,jQuery.camelCase,jQuery.nodeName

            noop:function(){},
            //用于在全局作用域执行javascript代码,这里暂略
            globalEval:function(data){},
            //转换连字符字符串为驼峰类型
            camelCase:function(string){
                return string.replace(rmsPrefix,'ms-').replace(rdashAlpha,fcamelCase);
            },
            //判断elem的nodeName是否=name
            nodeName:function(elem,name){
                return elem.nodeName&&elem.nodeName.toLowerCase()==name.toLowerCase();
            },
    jQuery.noop/globalEval,camelCase,nodeName

    2.9 jQuery.makeArray,jQuery.inArray

           makeArray:function(array,results){
                var ret=results||[],
                    type=jQuery.type(array);
                //undefined,null都会==null
                if(array!=null){
                    //1,没有length属性,或者具有length属性,但是是以下几种情况的
                    //2.如果array是string 的length表示字符串的长度
                    //3.如果array是函数,其length代表函数生命时的参数个数
                    //4,如果array是window对象,属性Length返回窗口中的框架(frame,iframe)个数
                    if(array.length==null|| type=='string' || type=='function' ||type=='regexp'||jQuery.isWindow(array)){
                        core_push.call(ret,array);
                    }else{//否则说明是类数组对象
                        jQuery.merge(ret,array);
                    }
                }
                return ret;
            },
              
            inArray:function(elem,array,i){
                return array==null?-1:core_indexOf.call(array,elem,i);
            },
    jQuery.makeArray,/inArray

    2.10 jQuery.merge

       //用于合并两个数组的元素到第一个数组中
            //事实上,jquery源代码中第一个参数可以是数组或者类数组对象,第二个参数可以是数组、类数组对象或任何含有连续整型属性的对象
            //第一个参数是数组,最后返回数组;第一个参数是类数组,则返回类数组
            merge:function(first,second){
                var l=second.length,
                    i=first.length,
                    j;
                for(j=0;j<l;j++){
                    first[i++]=second[j];
                }
                first.length=i;
                return first;
            },
    jQuery.merge

    2.11 jQuery.guid

        guid:1,    

    2.12 jQuery.proxy

            //该方法用于更改函数的执行上下文
            //源代码中有两种传参形式,这里仅考虑最常见的一种
            proxy:function(fn,context){
                if(!jQuery.isFunction(fn)){
                    return undefined;
                }
                var args=core_slice.call(arguments,2);
                    proxy=function(){
                        return fn.call(context||this,core_concat.call(args,core_slice.call(arguments)));
                    };
                proxy.guid=fn.guid=fn.guid||jQuery.guid++;
                return proxy;
            },
    View Code

    2.13 (todo) jQuery.access

            //用一个方法同时实现get和set操作
            //如何设置或者获取由回调函数fn确定
            //这个方法的实现等用到的时候结合来看
            access: function( elems, fn, key, value, chainable, emptyGet, raw ){
                
            },
    jQuery.access

     2.14 jQuery.now,jQuery.swap

            now:Date.now,
            //该方法用于交换css样式,在support模块较多用到
            //要交换的样式由参数options传递
            swap: function( elem, options, callback, args ){
                var name,ret,
                    old={};
                for(name in options){
                    old[name]=elem.style[name];
                    elem.style[name]=options[name];
                }
                ret=callback.call(elem,args||[]);
                for(name in options){
                    elem.style[name]=old[name];
                }
                return ret;
            },
    jQuery.now/swap

    截止目前,myJquey的当前版本代码:

    (function(window,undefined){
        var rootjQuery,
            core_version='2.0.3',
            idExpr=/^#([w-]*)$/,
            //下面两个正则用于转驼峰
            rmsPrefix = /^-ms-/,
            rdashAlpha = /-([da-z])/gi,
            class2type={},
            core_deletedIds=[],
    
            _jQuery=window.jQuery,
            _$=window.$,
    
            core_toString=class2type.toString,
            core_hasOwn=class2type.hasOwnProperty,
            core_trim=core_version.trim,
            core_indexOf=core_deletedIds.indexOf,
            core_push=core_deletedIds.push,
            core_concat=core_deletedIds.concat,
            core_slice=core_deletedIds.slice,
            //用于jQuery.camelCase转驼峰函数中
            //当replace函数只有一个匹配项时,第二个参数可以是一个函数
            //如果repalce中的正则没有捕获组,会向这个函数传递三个参数:模式的匹配项,模式匹配项在字符串中的位置,原始字符串
            //如果replace中的正则有捕获组,也会向这个函数传递三个参数,模式的匹配项,捕获组的匹配项,模式匹配项在字符串中的位置
            fcamelCase=function(all,letter){
               return letter.toUpperCase();            
            },
            jQuery=function(selector,context){
                return jQuery.fn.init(selector,context,rootjQuery);
            };
    
        jQuery.fn=jQuery.prototype={
            constructor:jQuery,
            init:function(selector,context,rootjQuery){
                var match,elem;
               //selector是选择器表达式
               if(typeof selector ==='string'){
                    match=idExpr.exec(selector);
                    if(match&&!context){
                        elem=document.getElementById(match[1]);
                        if(elem&&elem.parentNode){
                            this[0]=elem;
                            this.length=1;                        
                        }
                        this.selector=selector;
                        this.context=document;
                        return this;
                    }else{
                        //说明是复杂的选择器表达式,这里暂不考虑
                    }                
               }
               //处理selector是DOM元素的情形
               if(selector&&selector.nodeType){
                    this[0]=selector;
                    this.length=1;
                    this.context=selector;
                    return this;
               }
               //处理selector是函数的情形
               if(jQuery.isFunction(selector)){
                    return rootjQuery.ready( selector );
               } 
               //处理selector是jQuery对象的情形
               if(selector.selector){
                    this.selector=selector.selector;
                    this.context=selector.context;
               }
               //处理其他情形
               return jQuery.makeArray(selector,this);
    
            }
        };
    
        jQuery.fn.init.prototype=jQuery.prototype;
    
        //可接受的参数类型如下:jQuery.extend([deep],target,object1,[objectN])
        jQuery.extend=jQuery.fn.extend=function(){
            var target=arguments[0]||{},//指向目标对象
                deep=false,//是否进行深度复制
                i=1,//表示源对象的起始下标
                length=arguments.length,//表示参数个数;
                options,name,src,copy,copyIsArray;//options指向某个源对象,name指向源对象的某个属性名,src目标对象某个属性的原始值,copy某个源对象的某个属性的值,copyIsArray指示变量copy是否为数组        
            //首先进行参数修正
            if(typeof target==='boolean'){
                deep=target;
                target=arguments[1]||{};
                i=2;
            }
            //此时target就是jQuery或jQuery.fn
            if(i===length){
                target=this;
                i--;
            }
            //处理target是字符串或者其他情形,这在深度复制中可能出现
            // if(typeof target!=='object'||!jQuery.isFunction(target)){
            //     target={};
            // }
            for(i;i<length;i++){
                options=arguments[i];
                for(name in options){
                    src=target[name];
                    copy=options[name];
                    if(deep&&copy&&(jQuery.isPlainObject(object)||(copyIsArray=jQuery.isArray(object)))){
                        if(copyIsArray){
                            copyIsArray=false;
                            clone=src&&jQuery.isArray(src)?src:[];
                        }else{
                            clone=src&&jQuery.isPlainObject(src)?src:{};
                        }
                        target[name]=jQuery.extend(deep,clone,copy);
                    }else{
                        target[name]=copy;
                    }
                }    
            }
            return target;
        };
        //检查是否是数组或者类数组
        function isArrayLike(obj){
            var length=obj.length,
                type=jQuery.type(obj);
            if(obj&&jQuery.isWindow(obj)){
                return false;
            }
            if(obj.nodeType===1&&length){
                return true;
            }        
    
            if(type==='array'){
                return true;
            }
            if(typeof length==='number'&&(length==0||(length>0&&(length-1) in obj))){
                return true;
            }        
            return false;
        }
        jQuery.extend({
            //一堆静态方法和属性
            expando:'jQuery'+(core_version+Math.random()).replace(/D/g,''),
            // 该函数用于释放jQuery对于全局变量$的控制权,可选的参数deep代表是否释放对全局变量jQuery的控制权
            noConflict:function(deep){
                if(window.$===jQuery){
                    window.$=_$;
                }
                if(deep&&window.jQuery===jQuery){
                    window.jQuery=_jQuery;
                }
                return jQuery;
            },
            /********isReady,readyWait,holdReay,ready与加载事件有关,暂且略过***********/
            isReady:false,
            readyWait:1,
            holdReady:function(hold){},
            ready:function(){},
            /*******/
    
    
            /****下面是一系列类型检测的静态方法*******/
            isFunction:function(obj){
                //如果使用typeof,在有些浏览器中,正则也会返回function,因此这里采用jQuery处理后的方法,jQuery.type
                return jQuery.type(obj)==='function';
            },
            isArray:Array.isArray,
            isWindow:function(obj){
                return obj!==null&&obj===obj.window;
            },
            //判断obj是否为数字或者数字类型的字符串,并且是有效数字
            isNumeric:function(obj){
                return !isNaN(parseFloat(obj))&&isFinite(obj);
            },
            type:function(obj){
                if(obj===null){
                    return String(null);
                }
                //Date,Array等类型typeof都会返回object,function、正则(部分浏览器)中 typeof都会返回function
                 
                if(typeof obj==='object'||typeof obj==='function'){                
                    return class2type[core_toString.call(obj)];
                }
                return typeof obj;
            },
            //判断是否为以下两种情况:1,对象字面量;2,通过new Object()创建
            isPlainObject:function(obj){
                if(jQuery.type(obj)!=='object'||obj.nodeType||jQuery.isWindow(obj)){
                    return false;
                }
    
                //如果是纯粹的对象,那么obj一定有constructor属性,并且方法hasOwnPropertyOf一定就在构造函数本身的原型中,而不用通过原型链查找得到
               if(obj.constructor&&!core_hasOwn.call(obj.constructor.prototype,'isPrototypeOf')){
                    return false;
               }
               return true;
    
            },
            //检查是否是空对象
            isEmptyObject:function(obj){
                for(var name in obj){
                    return false;
                }
                return true;
            },
            /******类型检测静态方法结束********/
    
            error:function(msg){
                throw new Error(msg);
            },
            //将html字符串转换为html DOM结构,
            parseHTML: function( data, context, keepScripts ){
    
            },
            parseJSON:JSON.parse,
            parseXML:function(data){
                var xml, tmp;
                if ( !data || typeof data !== "string" ) {
                    return null;
                }
    
                // Support: IE9
                try {
                    tmp = new DOMParser();
                    xml = tmp.parseFromString( data , "text/xml" );
                } catch ( e ) {
                    xml = undefined;
                }
    
                if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
                    jQuery.error( "Invalid XML: " + data );
                }
                return xml;
            },
            noop:function(){},
            //用于在全局作用域执行javascript代码,这里暂略
            globalEval:function(data){},
            //转换连字符字符串为驼峰类型
            camelCase:function(string){
                return string.replace(rmsPrefix,'ms-').replace(rdashAlpha,fcamelCase);
            },
            //判断elem的nodeName是否=name
            nodeName:function(elem,name){
                return elem.nodeName&&elem.nodeName.toLowerCase()==name.toLowerCase();
            },
            //jQuery遍历方法,其中args是传递给回调callback的参数,仅供jQuery内部使用;外部调用该方法时,回调的参数默认为数组下标/对象key,对应数组值/对象value
            each:function(object,callback,args){
                var i,
                    value, 
                    length=object.length,
                    isArray=isArrayLike(object);
    
                if(args){//说明是内部调用
                    if(isArray){
                        for(i=0;i<length;i++){
                           value= callback.call(object[i],args);
                           if(value===false){
                                break;
                           }
                        }
                    }else{
                        for(i in object){
                            value=callback.call(object[i],args);
                            if(value===false){
                                break;
                            }
                        }
                    }
                }else{
                    if(isArray){
                        for(i=0;i<length;i++){
                            value=callback.call(object[i],i,object[i]);
                            if(value===false){
                                break;
                            }
                        }
                    }else{
                        for(i in object){
                            value=callback.call(object[i],i,object[i]);
                            if(value===false){
                                break;
                            }
                        }
                    }
                }
                return object;
            },
            trim:function(str){
                return str==null?'':core_trim.call(str);
            },
            //将一个类数组对象转换为真正的对象
            //results参数仅供jquery内部使用,此时在该参数的基础上添加元素
            makeArray:function(array,results){
                var ret=results||[],
                    type=jQuery.type(array);
                //undefined,null都会==null
                if(array!=null){
                    //1,没有length属性,或者具有length属性,但是是以下几种情况的
                    //2.如果array是string 的length表示字符串的长度
                    //3.如果array是函数,其length代表函数生命时的参数个数
                    //4,如果array是window对象,属性Length返回窗口中的框架(frame,iframe)个数
                    if(array.length==null|| type=='string' || type=='function' ||type=='regexp'||jQuery.isWindow(array)){
                        core_push.call(ret,array);
                    }else{//否则说明是类数组对象
                        jQuery.merge(ret,array);
                    }
                }
                return ret;
            },
              
            inArray:function(elem,array,i){
                return array==null?-1:core_indexOf.call(array,elem,i);
            },
            //用于合并两个数组的元素到第一个数组中
            //事实上,jquery源代码中第一个参数可以是数组或者类数组对象,第二个参数可以是数组、类数组对象或任何含有连续整型属性的对象
            //第一个参数是数组,最后返回数组;第一个参数是类数组,则返回类数组
            merge:function(first,second){
                var l=second.length,
                    i=first.length,
                    j;
                for(j=0;j<l;j++){
                    first[i++]=second[j];
                }
                first.length=i;
                return first;
            },
            //用于查找数组中满足过滤函数的元素,形成新的数组之后返回,原数组不受影响
            //如果inv未传入或者是false,元素只有在过滤函数返回true时,才会被保存在最终的结果数组中
            //如果参数inv是true,则恰好相反
            grep:function(elems,callback,inv){
                var i,
                    ret=[],
                    length=elems.length,
                    retVal;
                inv=!!inv;
                for(i=0;i<length;i++){
                    retVal=!!callback.call(elems[i],i);
                    if(retVal!==inv){
                        ret.push(elems[i]);
                    }
                }
                return ret;             
            },
            //用于对数组中每个元素执行callback操作,并将结果形成新的数组返回
            //参数arg仅仅是jQuery内部使用
            map:function(elems,callback,arg){
                var ret=[],
                    retVal,
                    i,
                    length=elems.length,
                    isArray=isArrayLike(elems);
                if(isArray){
                    for(i=0;i<length;i++){
                        retVal=callback.call(elems[i],i,arg);
                        if(retVal!=null){
                            ret.push(retVal);
                        }
                    }
                }else{
                    for(i in elems){
                        retVal=callback.call(elems[i],i,arg);
                        if(retVal!=null){
                            ret.push(retVal);
                        }
                    }
                }
                //保证最终返回的是一维数组
                return core_concat.call([],ret);
            },
            guid:1,
            //该方法用于更改函数的执行上下文
            //源代码中有两种传参形式,这里仅考虑最常见的一种
            proxy:function(fn,context){
                if(!jQuery.isFunction(fn)){
                    return undefined;
                }
                var args=core_slice.call(arguments,2);
                    proxy=function(){
                        return fn.call(context||this,core_concat.call(args,core_slice.call(arguments)));
                    };
                proxy.guid=fn.guid=fn.guid||jQuery.guid++;
                return proxy;
            },
            //用一个方法同时实现get和set操作
            //如何设置或者获取由回调函数fn确定
            //这个方法的实现等用到的时候结合来看
            access: function( elems, fn, key, value, chainable, emptyGet, raw ){
                
            },
            now:Date.now,
            //该方法用于交换css样式,在support模块较多用到
            //要交换的样式由参数options传递
            swap: function( elem, options, callback, args ){
                var name,ret,
                    old={};
                for(name in options){
                    old[name]=elem.style[name];
                    elem.style[name]=options[name];
                }
                ret=callback.call(elem,args||[]);
                for(name in options){
                    elem.style[name]=old[name];
                }
                return ret;
            },
            
        });
    
        //目前,js中typeof的返回值有六种:"number," "string," "boolean," "object," "function," 和 "undefined."
        //通过object.prototype.toString/或者{}.toString 返回值有九种:Boolean Number String Function Array Date RegExp Object Error,其中的Array,Date,RegExp,Object,Error都属于Object类型,在有些浏览器中typeof 正则会返回function
        jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(i,name){
            class2type["[object "+name+"]"]=name.toLowerCase();
        });
        //console.log(class2type,class2type);
        rootjQuery=jQuery(document);
        window.jQuery=window.$=jQuery;
    })(window);
    myJquery161010
  • 相关阅读:
    LoadRunner11 问题记录
    安装依赖包时,编译提示依赖库未安装,但实际上已经安装
    Close_wait进程过多
    JS中的混合模式
    JS面相对象
    JS中的工厂模式
    函数式编程Map()&Reduce()
    JavaScript函数参数与调用
    JavaScript中的prototype
    循环
  • 原文地址:https://www.cnblogs.com/bobodeboke/p/5941097.html
Copyright © 2020-2023  润新知