美文网首页
三(补充)jQuery源码中jQuery实例方法pushStac

三(补充)jQuery源码中jQuery实例方法pushStac

作者: 雪燃归来 | 来源:发表于2020-06-12 11:25 被阅读0次

       在上面的一片文章《三、(补充)jQuery源码中init方法详解》中,我们介绍了jQuery实例方法init的实现逻辑,本篇文章,我们再来介绍一个jQuery中比较基础,也比较常用的方法pushStack,这个方法实现了jQuery中出栈、入栈的相关操作。
       首先,来看一下它的源码

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;
}

一、pushStack方法逻辑分析

1、pushStack方法的使用

<div>div</div>
<span>span</span>
<script>
   $('div').pushStack($('span')).css('background','red')
</script>

       这段代码的运行结果如下



       为什么会出现这样的结果呢?我们执行下面的代码。

<div>div</div>
<span>span</span>
<script>
   console.log($('div').pushStack($('span')))
</script>

       可以看到返回的结果确实是jQuery('span')对象,不过这个对象中,多出来了一个我们比较默认的属性prevObject,并且这个属性指向的是jQuery('div')这个元素,哈哈 ,这一切的一切到底是什么意思呀!不要着急,请您看下面的解释。

2、pushStack方法的逻辑分析

       在执行完代码$('div').pushStack($('span'))后,jquery会为我们维护一个调用栈,栈的结构如下图所示:

调用栈
从图中,我们可以看出,将$('div')压入到了栈底,$('span')放到了$('div')的上一层,$('span')中含有一个属性指向$('div')的属性prevObject,所以上面的代码最后返回的结果就是栈顶元素$('span'),所以会得出上面的那种结果。
       结合上面的分析,我们再来看一下源码.
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;

源码中通过jQuery,merge方法合并了新的jquery对象ret,在ret上面添加prevObject属性,并指向调用pushStack方法的jquery对象(上层对象),同时将上层对象的上下文对象context传递给ret,最后将ret对象返回。通过上面的逻辑,我们就可以维护一个jquery对象的调用栈了

       这个方法在平常的开发中用的比较少,这是因为pushStack这个方法是提供给jquery内部使用的,在外部并没有多少开发场景可以真正地使用到它。

二、pushStack在其他方法中使用场景

       我们在上面的分析中提及到了prevObject这个属性,它指向的是调用栈中的下一层jquery对象,那下面,我们就来仔细看一下下面这个属性使用场景吧。

1、在jQuery实例方法end中的使用

<div>div</div>
<span>span</span>
<script>
 $('div').pushStack($('span')).css('background','red').end().css('background','blue')
</script>

       上面的这段代码的运行结果如下:

jquery实例方法end
       对于上面的结果,我们通过分析源码找到答案。看到了吗?是返回了prevObject属性,自然会指向$('div')这个jQuery对象。
end: function() {
  return this.prevObject || this.constructor(null);
}

2、在jQuery实例方法slice中的使用

<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
<span>span</span>
<script>
   $('div').slice(1,3).css('background','red')
</script>

上面代码的运行结果如下:


       我们依旧还是通过源码来分析一下这段代码的执行逻辑。哈哈,很简单吧,通过apply方法调用数组的slice方法,然后再将其推入到栈顶来完成我们的逻辑。
slice: function() {
    return this.pushStack( core_slice.apply( this, arguments ) );
}

3、在jQuery实例方法eq中的使用

<div>div</div>
<div>div</div>
<div>div</div>
<div>div</div>
<span>span</span>
<script>
   $('div').eq(1).css('background','red')
</script>

       上面的代码运行结果如下:



这段代码我们都非常熟悉,同样,让我们来看一下它的实现原理吧。

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

其实jquery中eq这个方法中还是有很多设计令人惊叹的。首先j = +i + ( i < 0 ? len : 0 ),大家知道为什么是+i,而不直接是i,这是为了防止某些人传递给eq方法的是 字符串‘-1’,而不是number类型的-1,此处通过+将字符串转化成数字。然后就是调用pushStack方法,将其放到栈的最顶端。
       当然,在jquery中用到pushStack的地方还有很多,此处并没有意义罗列。最后感谢您的阅读!

相关文章

网友评论

      本文标题:三(补充)jQuery源码中jQuery实例方法pushStac

      本文链接:https://www.haomeiwen.com/subject/hcqgtktx.html