jQuery源码阅读5— jQuery原型属性和方法

671 查看

整体架构:

jQUery.fn = jQUery.prototype = {
    constructor: jQUery,
    init : function(selector, context, rootjQuery){}
    selector: "";
    jquery: "1.7.1",
    length: 0,
    size: function(){},
    toArray: function(){},
    get: function(){},
    pushStack: function(elems, name, selector){},
    each: function(callback, args){},
    ready: function(fn){},
    eq: function(i){},
    first: function(){},
    last: function(){},
    slice: function(),
    map: function(callback){},
    end: function(){},
    push: push,
    sort: [].sort,
    splice: [].splice
}

一、selector、.jquery、.length、.size()

selector用于记录jQuery查找和过滤DOM元素时的选择器表达式
ex:
    $('div').find('p').selector //"div p"
    #('div p').selector //"div p"

二、toArray()、.get([index])

1、toArray()
.toArray()借用数组方法slice()将当前jQuery对象转换为真正的数组

源码:
toArray: function(){
    return Array.prototype.slice.call(this, 0);
},

复习 call()、 apply()

2.get([index])
返回当前jQuery对象中制定位置的元素或包含了全部元素的数组。
    如果没参数,则调用.toArray()返回包含了所有元素的数组。
    如果指定了参数index,则返回一个单独的元素;
    参数index从0开始计算,并支持附属,负数表示从元素集合末尾开始计算

    get: function(num){
        return num == null? this.toArray(): (num < 0 ? this[ this.length + num ]:this[num])
    }

三、each(function(index,Element))、jQuery.each(collection,callback(indexInArray, valueOfElement))

1、.each()遍历当前对象,并在每个元素上执行回调函数。当回调执行时,会传递当前循环次数作为参数,从0开始计数;
    回调函数是在当前元素为上下文的语境中触发的,即关键字this总是指向当前元素;回调函数中返回false可以终止遍历;

    each: function(callback, args){
        return jQUery.each(this,callback, args)
    }

2、jQuery.each(collection, callback(indexInArray, valueOfElement))
    静态方法jQuery.each()是个通用的遍历迭代方法,用于无缝遍历对象和数组。对于含有length属性的类数组对象,该方法通过下标遍历。
    对于其他对象则通过属性名遍历(for-in),遍历过程中,如果回调函数返回false,则遍历结束

    jQuery源码:

    each: function( object, callback, args ) {
        //object:待遍历的对象和数组
        //callback:对数组或对象每个属性都执行的回调函数
        //args:传给回调函数callback的参数数组,如果没有传入参数args,则执行回调时传入两个参数(下标(属性)、对应元素(属性值)),如果传入了args,则只把该参数传给回调函数

        var name, i = 0,
            length = object.length,
            isObj = length === undefined || jQuery.isFunction( object );

        if ( args ) {
            //如果传入参数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
        } else {
            //不传args
            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;
        //返回传入的形参object来支持链式语法
    }

四、 .map(callback(index,domElement))、jQuery.map(arrayOrObject, callback(value, indexOrKey))

1、 .map()遍历当前jQuery对象,在每个元素上执行回调函数,并将回调函数的返回值放入一个新jQuery对象中,常用于获取或设置DOM元素集合的值
    方法.map()内部通过静态方法jQuery.map()和圆形方法.pushStack()实现,相关代码如下所示:

    
    map: function(callback){
        return this.pushStack(jQUery.map(this, function(elem,i){
            return callback.call(elem, i, elem);
        }));
    }

2、jQuery.map(arrayOrObject, callback(value, indexOrKey))
    对数组中每个元素或对象的每个属性调用一个回调函数,并将回调函数的返回值放入一个新的数组中。
    回调函数执行时需要两个参数:1、数组元素或属性值,2、元素下标或属性名。
    关键字this指向全局对象window,回调函数的返回值会被放入新文组

    源码:
    // arg is for internal usage only
    map: function( elems, callback, arg ) {
        // elems:待遍历的数组或对象;
        // callback:回调函数,会在数组每个元素或对象上执行
        // args:仅限jQuery内部使用,如果调用jQuery.map()时传入了参数arg,则会传给回调函数callback
        var value, key, ret = [],
            i = 0,
            length = elems.length,
            // jquery objects are treated as arrays
            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
        if ( isArray ) {
            for ( ; i < length; i++ ) {
                value = callback( elems[ i ], i, arg );

                if ( value != null ) {
                    ret[ ret.length ] = value;
                }
            }

        // Go through every key on the object,
        } else {
            for ( key in elems ) {
                value = callback( elems[ key ], key, arg );

                if ( value != null ) {
                    ret[ ret.length ] = value;
                }
            }
        }

        // Flatten any nested arrays
        return ret.concat.apply( [], ret );
    },

五、 .pushStack(elements, name, arguments)

原型.pushStack()创建一个新的空jQuery对象,然后把DOM元素集合放入这个jQuery对象中,并保留对当前jQUery对象的引用。
原型方法.pushStack()是核心方法之一,为很多方法提供了支持

// Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
    // Build a new jQuery matched element set
    var ret = this.constructor();

    if ( jQuery.isArray( elems ) ) {
        push.apply( ret, elems );

    } else {
        jQuery.merge( ret, elems );
    }

    // Add the old object onto the stack (as a reference)
    ret.prevObject = this;

    ret.context = this.context;

    if ( name === "find" ) {
        ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
    } else if ( name ) {
        ret.selector = this.selector + "." + name + "(" + selector + ")";
    }

    // Return the newly-formed element set
    return ret;
},

六、 .end()

结束当前链条中最近的筛选操作,并将匹配元素集合还原为之前状态
end: function(){
    return this.prevObject || this.consgructor(null);
}