jQuery源码分析之jQuery.eq()和jQuery.get()方法比较

来源:互联网 发布:手机淘宝怎么投诉客服 编辑:程序博客网 时间:2024/06/16 14:37

首先来一段测试代码:

<div id="test">   <div id="child"></div></div>
JS部分:

//这里要记住了:通过源码分析,如果length不在有效范围之内那么传入pushStack//的参数是[]也就是空对象,所以返回空的jQuery对象!//打印:function(a,b){return new m.fn.init(a,b)}//$("div").constructor.length表示形参的个数alert("选择器构造函数:"+$("div").constructor);//打印[object HTMLDocument]alert("选择器上下文:"+$("child").context);//下面打印true,说明选择器返回对象的contructor是jQuery对象alert($("div").constructor() instanceof jQuery);//merge函数调用之前不是jQuery对象,这是和get或者下标访问一样的结果只是DOMalert("merge函数调用之前->"+([$("div")[0]] instanceof jQuery))//返回false//merge函数通过把DOM对象的属性逐个封装到jQuery对象上,构建jQuery对象返回var ret = jQuery.merge( $("div").constructor(), [$("div")[0]]);alert("merge函数调用后->"+(ret instanceof jQuery));//打印true,merge后已经是jQuery对象了//这里为undefined,因为我是直接merge,没有调用pushStack,所以没有封装到prevObject。调用eq就相当于调用pushStack方法了!alert("新jQuery返回旧的jQuery"+(ret.prevObject));//也就是如果需要访问原来的选择器结果对象,如$("p")那么应该用prevObject//下面返回truealert("调用eq后就会有prevObject->"+($("div").eq(0).prevObject instanceof jQuery));

测试代码2:

//下面返回“test”,也就是说调用eq后如果要获取到上一次的选择结果,就可以用prevObject。因为调用eq的时候通过prevObject保存了上一次的this,//也就是选择的jQuery对象。$("div").eq(0).prevObject相当于$("div")alert($("div").eq(0).prevObject.eq(0).attr("id"));

测试代码3:

alert($("p").eq(1).constructor); // 打印:function(a,b){return new m.fn.init(a,b)}

eq源码分析:

 eq: function( i ) {var len = this.length,j = +i + ( i < 0 ? len : 0 );//可以传入数字字符串!因为+就是将他变成数字!//传入的参数是[this[j]]=[DOM元素]=[$("p")[0]]return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );}

因为eq方法调用了pushStack所以他的返回值类型是jQuery类型;同时在pushStack中调用了jQuery.merge里面把所有的这里的DOM数组中的对象封装到一个空的jQuery对象上面并且返回!

pushStack源码:关于context详见codeplayer

 pushStack: function( elems ) {// Build a new jQuery matched element set//创建新的jQuery对象集合var ret = jQuery.merge( this.constructor(), elems );// Add the old object onto the stack (as a reference)//用prevObject保存选择器的结果,也就是上面的eq函数的this对象ret.prevObject = this; //保存上下文,默认是documentret.context = this.context//eq方法归根到底还是通过下标访问来完成的,通过把访问的下标的DOM对象逐个封装到空的JQuery对象中完成新的jQuery对象的构建!// Return the newly-formed element setreturn ret;}

get方法源码:

get: function( num ) {return num != null ?// Return just the one element from the set( num < 0 ? this[ num + this.length ] : this[ num ] ) ://如果没有参数,如$("ul li").get()调用,那么this就是指$("ul li")的选择结果是jQuery对象,通过slice后返回的对象是Array// Return all the elements in a clean arrayslice.call( this );}

我们看到如果调用get方法时候没有传入参数,那么调用了[].slice.call方法,从而把类数组的jQuery对象转化为了Array类型了!

测试例子:

//返回false,get方法返回的是DOM对象alert($("ul li").get() instanceof jQuery);alert($("ul li").get());//返回[object HTMLLiElement],[object HTMLLiElement],[object HTMLLiElement]//没有参数返回是数组,结果为truealert($("ul li").get() instanceof Array);//get没有参数的时候,this是jQuery对象,也就是选择器的结果如$("ul li")//通过slice就可以把jQuery对象$("ul li")转化为JS对象.下面返回都是truealert(Array.prototype.slice.call($("ul li")) instanceof Array);alert(Array.prototype.slice.call($("#me")) instanceof Array);
总结:

(1)通过源码分析,传入到eq函数的length不在有效范围之内那么传入pushStack的参数是[]也就是空对象! 这时候返回的jQuery对象不包含任何DOM对象!
(2)var ret = jQuery.merge( $("div").constructor(), [$("div")[0]]); 可以把后面数组中的对象全部封装到前面的空的jQuery对象上面,构成一个新的jQuery对象!

(3)对于get方法我们通过是下标来访问的,如果没有传入参数那么通过slice返回整个调用对象的DOM集合,否则返回特定的项。如果是负数,那么eq和get是一样的,都是通过加上调用对象的长度!

0 0
原创粉丝点击