小An
2014-12-28 23:01
请教一个问题,关于end(),如果调用遍历方法,它改变堆栈,我们使用end()方法,ok没问题,返回上一个堆栈对象,下面这个例子我不是很理解:
<div>测试内容1</div>
<div>测试内容2</div>
<script>$('<p>新增内容</p>').appendTo('div').addClass('c1').end().addClass('c2');</script>
为什么end()之后的对象是第二个p?而不是新增的'<p>新增内容</p>',为什么是一个p,不是[p,p]
感谢版主的回答,特意看了一下appendTo的源码
jQuery.each({ appendTo: "append", prependTo: "prepend", insertBefore: "before", insertAfter: "after", replaceAll: "replaceWith" }, function( name, original ) { jQuery.fn[ name ] = function( selector ) { var elems, i = 0, ret = [], insert = jQuery( selector ), last = insert.length - 1; for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone(true); jQuery( insert[i] )[ original ]( elems ); // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() core_push.apply( ret, elems.get() ); } return this.pushStack( ret ); }; });
1)insert取得选择器div的2个对象,然后进行循环
2)第一次循环elems保存this($('<p>新增内容</p>'))的克隆,然后经过jQuery( insert[i] )[ original ]( elems );这里面主要是调用的$(div)的append()方法,而append()方法主要调用js的原生态的appendChild()方法,导致的结果就是,div跟elems有了父子关系,注意这里的elems只是克隆所以不影响this,这时debug可以看到elems是有parentElement的(第一个div);core_push不多说,存放数据组的。
3)第二次循环elems=this,这一句很关键,直接跟this绑定,然后elems再执行刚才的第一次Query( insert[i] )[ original ]( elems )这个过程,这时候的insert[i]是第二个div,理所当然的this和elems跟第二个div绑定成了,有了父子关系
4)循环结束进入我们堆栈操作this.pushStack( ret ),里面比较简单
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; },
返回数组的prevObject设置成第三步的this
这个问题问的很好,为什么不是数组的[p,p]?
这里我们要从本质上出发,我这个p是怎么来的?
是通过
$('<p>新增内容</p>')
产生的,但是这个p元素是不是只有一个?
只是通过appendTo('div')的时候,会产生二个,其实是因为appendTo内部在调用文档碎片clone了一个p,所以才会存在2个p元素
那么end的本质是调用prevObject的引用,prevObject其实是保存最终引用的
$('<p>新增内容</p>')
这个产生的p,所以为什么只有一个的原因了
jQuery源码解析(架构与依赖模块)
84047 学习 · 280 问题
相似问题