问答详情
源自:2-7 end与addBack

end疑问

请教一个问题,关于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]



提问者:小An 2014-12-28 23:01

个回答

  • 小An
    2015-01-04 23:29:49

    感谢版主的回答,特意看了一下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

  • 艾伦Aaron
    2014-12-30 10:15:36

    这个问题问的很好,为什么不是数组的[p,p]?


    这里我们要从本质上出发,我这个p是怎么来的?
    是通过

    $('<p>新增内容</p>')

    产生的,但是这个p元素是不是只有一个?
    只是通过appendTo('div')的时候,会产生二个,其实是因为appendTo内部在调用文档碎片clone了一个p,所以才会存在2个p元素

    那么end的本质是调用prevObject的引用,prevObject其实是保存最终引用的

    $('<p>新增内容</p>')

    这个产生的p,所以为什么只有一个的原因了