• jquery 源码分析四(下)


    接下去分析那个extend块,接下来是一个each函数,它对传入的数组中的每个值进行特定处理,根据返回值确定操作(明确返回 false则停止循环)

    each: function( obj, callback, args ) {
        var value,
            i = 0,
            length = obj.length,
            isArray = isArraylike( obj );
    
        if ( args ) {
            if ( isArray ) {
                for ( ; i < length; i++ ) {
                    value = callback.apply( obj[ i ], args );
    
                    if ( value === false ) {
                        break;
                    }
                }
            } else {
                for ( i in obj ) {
                    value = callback.apply( obj[ i ], args );
    
                    if ( value === false ) {
                        break;
                    }
                }
            }
    
        // 不需要传入args时,这是一种each较常用的形式
        } else {
            if ( isArray ) {
                for ( ; i < length; i++ ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );
    
                    if ( value === false ) {
                        break;
                    }
                }
            } else {
                for ( i in obj ) {
                    value = callback.call( obj[ i ], i, obj[ i ] );
    
                    if ( value === false ) {
                        break;
                    }
                }
            }
        }
    
        return obj;
    }

    trim函数主要是用来去除字符串首尾的空格,优先使用浏览器中自带有的方法。makeArray则是将传入的一或两个参数转成数组返回,看源码分析如下:

    trim: trim && !trim.call("uFEFFxA0") ?
        function( text ) {
            return text == null ?
                "" :
                trim.call( text );
        } :
        // 优先使用自带的trim
        // 否则就返回自己设置的trim函数
        function( text ) {
            return text == null ?
                "" :
                ( text + "" ).replace( rtrim, "" );   
                    // rtrim = /^[suFEFFxA0]+|[suFEFFxA0]+$/g
        },
    
    makeArray: function( arr, results ) {
        var ret = results || [];
    
        if ( arr != null ) {
            // 当arr为数组或类数组时,用merge(后面就会分析到)
            if ( isArraylike( Object(arr) ) ) {
                jQuery.merge( ret,
                    typeof arr === "string" ?
                    [ arr ] : arr
                );
            } else {
               // 否则,就直接将arr作为一个元素添加到ret作为最后一项
                push.call( ret, arr );
            }
        }
    
        return ret;
    }

    inArray是用来判断从指定位置其某个元素是否在一个array中,merge是将后一个arr融合到前一个arr中(当然,也可能是类数组)

    inArray: function( elem, arr, i ) {
        var len;
    
        if ( arr ) {
                    // 优先使用自带的indexOf
            if ( indexOf ) {
                return indexOf.call( arr, elem, i );
            }
    
            len = arr.length;
            i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
    
            for ( ; i < len; i++ ) {
                if ( i in arr && arr[ i ] === elem ) {
                    return i;
                }
            }
        }
    
        return -1;
    },
    
    merge: function( first, second ) {
        var len = +second.length,
            j = 0,
            i = first.length;
    
        while ( j < len ) {
            first[ i++ ] = second[ j++ ];
        }
    
        // 为了兼容一些会返回length为NaN的情况的类数组(NodeList.....在某些浏览器中)
        if ( len !== len ) {
            while ( second[j] !== undefined ) {
                first[ i++ ] = second[ j++ ];
            }
        }
    
        first.length = i;
    
        return first;
    },

    grep作用是一个过滤的效果,对每隔元素执行一遍传入的函数,满足要求的就放入结果中。作为第三个invert参数,是为了设置是函数返回true还是false时才算通过过滤。 如果 'invert' 为 false ,则函数返回数组中由过滤函数返回 true 的元素,当'invert'为 true,则返回过滤函数中返回 false 的元素集。

    grep: function( elems, callback, invert ) {
        var callbackInverse,
            matches = [],
            i = 0,
            length = elems.length,
            callbackExpect = !invert;
    
        // 循环整个elems,对每个都进行callback函数的运行
        // 根据invert筛选结果
        for ( ; i < length; i++ ) {
            callbackInverse = !callback( elems[ i ], i );
            if ( callbackInverse !== callbackExpect ) {
                matches.push( elems[ i ] );
            }
        }
    
        return matches;
    }

    map和each类似,不同的是map会对每一项进行循环,不会因为返回值的问题而停止,同时会将所有非null的返回值组成数组返回。

    map: function( elems, callback, arg ) {
        var value,
            i = 0,
            length = elems.length,
            isArray = isArraylike( elems ),
            ret = [];
    
        // 如果是数组或类数组,就用i递增循环
        if ( isArray ) {
            for ( ; i < length; i++ ) {
                value = callback( elems[ i ], i, arg );
    
                if ( value != null ) {
                    ret.push( value );
                }
            }
    
        // 否则,就认为是object,用for..in方法
        } else {
            for ( i in elems ) {
                value = callback( elems[ i ], i, arg );
    
                if ( value != null ) {
                    ret.push( value );
                }
            }
        }
    
        // 返回数组副本,这样对新数组的修改不会影响到旧数组
        return concat.apply( [], ret );
    }

    proxy是一个可以改变执行函数上下文环境的函数,可以通过$.proxy(function(){},context)实现。(例:$( "#test" ).on( "click", $.proxy( me.test, me ) ) )。

    proxy: function( fn, context ) {
        var args, proxy, tmp;
            //确定fn和context确切值
        if ( typeof context === "string" ) {
            tmp = fn[ context ];
            context = fn;
            fn = tmp;
        }
    
        // 若fn不是函数,则直接返回
        if ( !jQuery.isFunction( fn ) ) {
            return undefined;
        }
    
        // 得到要传入的参数
        args = slice.call( arguments, 2 );
        proxy = function() {
            //args为在proxy中定义的变量,而arguments则是执行时会有的变量(> <解释不清楚...来个例子)
           //$( "#test" ).on( "click", $.proxy( me.test, me ) )运行时,arguments为[jQuery.events]
            return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
        };
    
        // 设置唯一的guid,这样可以在后期移除
        proxy.guid = fn.guid = fn.guid || jQuery.guid++;
    
        return proxy;
    },

    最后一个是now函数,返回现在的时间

    now: function() {
        return +( new Date() );
    }
  • 相关阅读:
    c++设计模式总结
    Java复习(四)类的重用
    Java复习(三)类中的方法
    Java复习(二)类与对象的基本概念
    Java复习(一)——Java语言概述、开发环境、基础知识
    Java复数的加乘除运算
    人见人爱A+B
    noj快排
    noj最长公共子序列
    C语言里有没有sort函数?有!
  • 原文地址:https://www.cnblogs.com/cyITtech/p/3587089.html
Copyright © 2020-2023  润新知