jquery 源码分析二

以下这一段函数出现在实例化jQuery对象函数之后,是jQuery的prototype的最基本的几个函数,分析前先看这几个相关的常量和一些函数:

var deletedIds = [];

var slice = deletedIds.slice;

var concat = deletedIds.concat;

var push = deletedIds.push;

var indexOf = deletedIds.indexOf;
merge: function( first, second ) {
        var len = +second.length,
            j = 0,
            i = first.length;

        while ( j < len ) {
            first[ i++ ] = second[ j++ ];
        }

        // Support: IE<9
        // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
        if ( len !== len ) {
            while ( second[j] !== undefined ) {
                first[ i++ ] = second[ j++ ];
            }
        }

        first.length = i;

        return first;
    }
map: function( elems, callback, arg ) {
        var value,
            i = 0,
            length = elems.length,
            isArray = isArraylike( elems ),
            ret = [];

        // 若是数组,则直接从0开始循环,每项都执行callback,返回值保存在ret中
        if ( isArray ) {
            for ( ; i < length; i++ ) {
                value = callback( elems[ i ], i, arg );

                if ( value != null ) {
                    ret.push( value );
                }
            }

        // 若是对象,就用for in循环,每项执行callback,返回值保存在ret中
        } else {
            for ( i in elems ) {
                value = callback( elems[ i ], i, arg );

                if ( value != null ) {
                    ret.push( value );
                }
            }
        }

        // 返回ret的副本
        return concat.apply( [], ret );
    }

首先是最前面的几个常量,先定义了一个空数组,然后后面的几个slice等变量就直接等于了数组的slice操作,这样对于jQuery生成的类数组来说,直接调用这些方法可以很好的处理一些事情。在后面的源码分析中也可以这些函数很多的调用。

接下来是Jquery下的merge函数(这两个函数都不是在prototype下,而是直接是jQuery的属性),merge函数用于将两个数组或类数组合并,首先是用数组的形式一项项合并,然后为了支持类数组,又加了一个判断,对类数组做支持。

然后是map函数,map函数对给予的数组或对象进行遍历,针对每一项执行callback函数,ret中保存的是最后callback计算所得的值,组成数组后返回。

接下来就是jQuery中prototype最初定义的几个函数进行分析,代码和分析如下:

jQuery.fn = jQuery.prototype = {
    // 定义当前jquery的版本,同时设定好constructor的指向,方便后面使用
    jquery: version,

    constructor: jQuery,

    // 初始选择器为空
    selector: "",

    // 默认的jQuery类数组长度为0
    length: 0,

    toArray: function() {
        return slice.call( this );
    },

    // 返回指定项的元素
    // 或者返回所有元素组成的数组
    get: function( num ) {
        return num != null ?

            // 如果存在num,则返回指定项元素
            ( num < 0 ? this[ num + this.length ] : this[ num ] ) :

            // 不存在num,则返回数组副本
            slice.call( this );
    },

    // 将一些列的elems放入新的JQuery中
    // 返回的是根据elems生成的新的JQuery
    pushStack: function( elems ) {

        // 建立新的JQuery
        var ret = jQuery.merge( this.constructor(), elems );

        // 将原始的JQuery对象放入prevObject中,方便后期返回
        ret.prevObject = this;
        ret.context = this.context;

        // 返回新生成的对象
        return ret;
    },

    // each和map都是对数组或对象进行遍历
    // 两者的区别在于,each遍历时,若某一项callback返回的是false,则停止遍历,最后返回的是经过处理的this
    // map则是将每一项传入的值进行计算,然后将结果组成一个数组返回
    each: function( callback, args ) {
        return jQuery.each( this, callback, args );
    },

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

    slice: function() {
        return this.pushStack( slice.apply( this, arguments ) );
    },

    first: function() {
        return this.eq( 0 );
    },

    last: function() {
        return this.eq( -1 );
    },

    eq: function( i ) {
        var len = this.length,
            j = +i + ( i < 0 ? len : 0 );
        return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
    },

    end: function() {
        return this.prevObject || this.constructor(null);
    },

    // 最后的end可以对以上用pushStack过的方法进行回溯,回到上一步的操作对象
    // 以下几个方法的添加使得JQuery更像数组
    push: push,
    sort: deletedIds.sort,
    splice: deletedIds.splice
};
原文地址:https://www.cnblogs.com/cyITtech/p/3579728.html