jQuery源码学习之四 (jQUery对象的实例属性和方法)

1、get()

     参数为null则返回DOM数组,否则返回相应的下标DOM元素(支持负数)

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


2、pushStack():jQuery的栈方法,与end()方法对应

     this.constructor指向函数jQuery,则 ret = jQuery.merge( this.constructor(), elems ) 将创建返回一个jQuery实例ret,然后将传入的elem扩充进去。通过ret.prevObject = this;指向调用pushStack()方法的jQuery实例对象。进一步可通过end()方法 返回上一个jQuery对象。(jQuery内部多处使用)

jQuery.fn = jQuery.prototype = {
...
pushStack: function( elems ) {
        var ret = jQuery.merge( this.constructor(), elems );
        ret.prevObject = this;
        ret.context = this.context;
        return ret;
    }
...
end: function() {
        return this.prevObject || this.constructor(null);
    }
...
};


3、each() : 调用$.each();

jQuery.fn = jQuery.prototype = {
...
each: function( callback, args ) {
         return jQuery.each( this, callback, args );
      },
<pre name="code" class="html">...
}


$.each()源码:

if 中提供的方法是jQuery的API中没有提供的,jQuery的API中提供的方法在else中(也是我们平时使用的$.each()的用法)。

先看外层else中代码:

      if 传入的第一个参数是数组[]或类数组eg:{0:"a",1:"b","length":2},则for循环,调用毁掉函数callback.call(obj[i],i,obj[i]),this指向obj[i],并将i,obj[i],作为参数传入。else 如果传入的是对象则用for in 进行循环。

外层if 中代码和外层else 中原理大致一样,只不过是接受了 第三个参数args,并利用了apply修改callback的this指向(args可以是数组或者类数组)

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;
            }
        }
    }
// A special, fast, case for the most common use of 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;
}

涉及到的函数$.isArraylick(),源码如下:


function isArraylike( obj ) {
	var length = obj.length,
            type = jQuery.type( obj );
	if ( jQuery.isWindow( obj ) ) {
		return false;
	}
	if ( obj.nodeType === 1 && length ) {
		return true;
	}
	return type === "array" || type !== "function" && ( length === 0 || typeof length === "number" && length > 0 && ( length - 1 ) in obj );
}

涉及到的函数:isWIndow()、$.type()

isWindow: function( obj ) {
		return obj != null && obj === obj.window;
	},
type: function( obj ) {
        if ( obj == null ) {
            return String( obj );
        }
        // Support: Safari <= 5.1 (functionish RegExp)
        return typeof obj === "object" || typeof obj === "function" ?
            class2type[ core_toString.call(obj) ] || "object" :
            typeof obj;
    },

$().ready

$().slice()

core_slice其实等价于[].slice,调用的其实是数组的slice方法,并用apply更改this指向,用pushStack重新生成新的jQuery对象并返回.

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

    first()、last() 都是调用eq()(支持负数的传入),用pushStack重新生成新的jQuery对象并返回.

        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] ] : [] );
 	},
$().map 调用$.map()
map: function( callback ) {
		return this.pushStack( jQuery.map(this, function( elem, i ) {
			return callback.call( elem, i, elem );
		}));
	},





相关jQUery源码:

jQuery.fn = jQuery.prototype = {
	// The current version of jQuery being used
	jquery: core_version,

	constructor: jQuery,
	init:{
        ...
        },
	selector: "",

	// The default length of a jQuery object is 0
	length: 0,

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

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this[ this.length + num ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems ) {

		// Build a new jQuery matched element set
		var ret = jQuery.merge( this.constructor(), elems );

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

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

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

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

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: core_push,
	sort: [].sort,
	splice: [].splice
};


posted @ 2014-07-23 11:19  hdchangchang  阅读(237)  评论(0编辑  收藏  举报