这次分析的方法跟前面不同,虽然pushStack也是原型方法之一,但是我们几乎从不用在页面调用,在参考手册里面也没有这个方法的使用说明,但是这个方法还是非常重要的,在使用很多jQuery的其他方式都会隐式的调用此方法:

它为以下方法提供支持:
‰ ‰ jQuery 对象遍历:.eq()、.first()、.last()、.slice()、.map()。
‰ ‰ DOM 查找、过滤:.find()、.not()、.filter()、.closest()、.add()、.andSelf()。
‰ ‰ DOM 遍历: .parent()、.parents()、.parentsUntil()、.next()、.prev()、.nextAll()、.prevAll()、
.nextUnit()、.prevUnit()、.siblings()、.children()、.contents()。
‰ ‰ DOM 插入: jQuery.before()、jQuery.after()、jQuery.replaceWith()、.append()、.prepent()、
.before()、.after()、.replaceWith()。

下面是1.7.1版本的源码

    // Take an array of elements and push it onto the stack
// (returning the new matched element set)
pushStack: function( elems, name, selector ) {
// Build a new jQuery matched element set
var ret = this.constructor(); if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems ); } else {
jQuery.merge( ret, elems );
} // Add the old object onto the stack (as a reference)
ret.prevObject = this; ret.context = this.context; if ( name === "find" ) {
ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
} else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
} // Return the newly-formed element set
return ret;
},

在英文注释里面已经告诉我们这个方法是干什么的了,就是把获取的元素数组放到栈中返回一个新的被匹配的数组,说白了就是在执行jQuery构造函数之后会产生一个实例对象,里面放着匹配到的元素,当使用这一个方法是就会在新建一个空的jQuery对象,然后把调用这个方法的对象匹配到的元素放到栈中,就是一个数组然后通过一个指针指向调用此方法的对象,这样就就是一个链式栈可以不断扩展。可以让我们实现“向后”操作,比如end()方法,下面分析源码:

‰ ‰ 参数 elems:将放入新 jQuery 对象的元素数组(或类数组对象) 。
‰ ‰ 参数 name:产生元素数组 elems 的 jQuery 方法名。
‰ ‰ 参数 selector:传给 jQuery 方法的参数,用于修正原型属性 .selector。

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

构造一个新的空 jQuery 对象 ret,this.constructor 指向构造函数 jQuery(),ret就是一个空的jQuery对象

 if ( jQuery.isArray( elems ) ) {
push.apply( ret, elems ); } else {
jQuery.merge( ret, elems );
}

判断一下elems是不是数组,如果不是用merge(后续分析)转换成数组,如果是放ret中,此时的elems是一个数组不能直接ret.push否则就会变成二维数组,这里也是巧妙的利用了apply的数组参数属性直接将一个数组的元素添加到另一个数组组,很好用的方法赶紧收藏!这样就实现了数据转移

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

既然是链式的那么必须有指针,在新对象中添加这么一个属性来指向当前的jQuery对象

if ( name === "find" ) {
ret.selector = this.selector + ( this.selector ? " " : "" ) + selector;
} else if ( name ) {
ret.selector = this.selector + "." + name + "(" + selector + ")";
}

给ret加一个selector属性,这里的selector并不是之前分析的原型属性selector表示的选择字符串,它的主要作用是为了调试方便,可以看到方法名和旧的对象的选择字符串以及传入的参数selector,至于为什么把find方法单独列出来还要等到find方法分析完再看吧

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

最后把新的jQuery对象返回出去,其实这个方法代码量不大就是思想比较难理解,为此调用下看下结构:

<!doctype html>
<html>
<head>
<meta charset='utf-8'/>
<title>jQuery源码分析-原型属性和方法</title>
</head>
<body>
<div>
</div>
<div><a></a></div>
</body>
<script src='jquery-1.7.1.js'></script>
<script>
console.dir($('a').parent().parent(0));
</script>
</html>

然后看下元素机构

这样就很容易理解了,这个时候再来看出栈的方法end()

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

原来这个方法就是找的prevObject,根据上面的结构图不难看出

$('a').parent().parent(0).end()

运行结果指向的是div元素这两个方法一进一出搭配使用,只不过是end方法是在页面大摇大摆的被使用参考手册也有其使用方法,而pushStack只能做一个幕后英雄啦

jQuery原型方法.pushStack源码分析的更多相关文章

  1. jQuery 2.0.3 源码分析Sizzle引擎解析原理

    jQuery 2.0.3 源码分析Sizzle引擎 - 解析原理 声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢! 先来回答博友的提问: 如何解析 div > p + ...

  2. jQuery 2.0.3 源码分析 Deferred(最细的实现剖析,带图)

    Deferred的概念请看第一篇 http://www.cnblogs.com/aaronjs/p/3348569.html ******************构建Deferred对象时候的流程图* ...

  3. jQuery 2.0.3 源码分析core - 选择器

         声明:本文为原创文章,如需转载,请注明来源并保留原文链接Aaron,谢谢!      打开jQuery源码,一眼看去到处都充斥着正则表达式,jQuery框架的基础就是查询了,查询文档元素对象 ...

  4. jQuery 2.0.3 源码分析 Deferred概念

    JavaScript编程几乎总是伴随着异步操作,传统的异步操作会在操作完成之后,使用回调函数传回结果,而回调函数中则包含了后续的工作.这也是造成异步编程困难的主要原因:我们一直习惯于“线性”地编写代码 ...

  5. jQuery 2.0.3 源码分析 事件绑定 - bind/live/delegate/on

    事件(Event)是JavaScript应用跳动的心脏,通过使用JavaScript ,你可以监听特定事件的发生,并规定让某些事件发生以对这些事件做出响应 事件的基础就不重复讲解了,本来是定位源码分析 ...

  6. jQuery 2.0.3 源码分析 事件体系结构

    那么jQuery事件处理机制能帮我们处理那些问题? 毋容置疑首先要解决浏览器事件兼容问题 可以在一个事件类型上添加多个事件处理函数,可以一次添加多个事件类型的事件处理函数 提供了常用事件的便捷方法 支 ...

  7. jQuery.lazyload使用及源码分析

    前言: 貌似以前自己也写过图片懒加载插件,但是新公司使用的是jQuery.lazyload插件,为了更好的运用,自己还是把源码看了遍,分别记录了如何使用, 插件原理,各个配置属性的完整解释,demo实 ...

  8. jQuery 2.0.3 源码分析 Deferrred概念

    转载http://www.cnblogs.com/aaronjs/p/3348569.html JavaScript编程几乎总是伴随着异步操作,传统的异步操作会在操作完成之后,使用回调函数传回结果,而 ...

  9. jQuery Deferred对象详细源码分析(-)

    本系列文章讲介绍这个Deferred东西到底拿来干什么,从1.5版本加进来,jQuery的很多代码都重写了.直接先上源码分析了,清楚了源码分析,下节将讲具体的应用 以及应用场景. 创建对象 var d ...

随机推荐

  1. 硬刚Google ,这家小公司的增长团队长啥样

    背景: AdRoll 是一家主打重定向广告(Retargeting)服务的技术公司,基于用户浏览记录等信息,为广告主提供几乎瞬时的广告位购买服务,当前估值15.5亿美元.吊打谷歌, AdRoll 已经 ...

  2. 献给所有从事IT行业拥有梦想的英语渣们

    本文适合读者:从小到大英语都不好,如今选择IT行业需要重拾英语追寻梦想的人,英语大神们请绕行.. 目录 一.背景介绍 二.明确学习目标 2.1 英文文法 2.2 词汇量 三.题外话 3.1 关于本文 ...

  3. WIN7 共享网络方法

    WIN7 共享网络方法 第一步: 按WIN+R调出“运行”栏,在“运行”菜单栏输入“cmd”,出现命令提示符,输入命令“netsh wlan set hostednetwork mode=allow ...

  4. git代码回滚:Reset、Checkout、Revert的选择

    代码回滚:Reset.Checkout.Revert的选择 Zhongyi Tong edited this page on Dec 8, 2015 · 5 revisions Pages 19 Ho ...

  5. Sql Server,如何去含有非数字的nvarchar,再转为为数值

    菜鸟一枚,今天做项目时,突然遇到一个问题: 在数据库中中存放的nvarchar类型的“时间”,例如:‘08:00’,而我需要进行时间的范围比较,这时就想到了将nvarchar类型转化为int类型. 这 ...

  6. IE9父容器overflow:auto时,子容器状态更改导致滚动条下出现额外空间的问题探讨

    IE的每次跟新都会有一些奇葩的bug,我们默默承受了. 这个问题在项目中出现困扰了我近一个星期,这里记录一下.看下面实例 <style> .panel{ width: 200px; ove ...

  7. Hyperledger中数据存取的实现

    简介 本文介绍了在Hyperledger中数据存取的实现. API接口 Hyperledger提供基于key/value的数据存储,其中key是字符串,value则是二进制字节数组,Hyperledg ...

  8. Java魔法堂:解读基于Type Erasure的泛型

    一.前言 还记得JDK1.4时遍历列表的辛酸吗?我可是记忆犹新啊,那时因项目需求我从C#转身到Java的怀抱,然后因JDK1.4少了泛型这样语法糖(还有自动装箱.拆箱),让我受尽苦头啊,不过也反映自己 ...

  9. 前端自动化开发之grunt

    上篇文章介绍了前端模块化开发工具seaJs,利用seaJs我们可以轻松实现前端的模块化编程,参见http://www.cnblogs.com/luozhihao/p/4818782.html 那么今天 ...

  10. log4net 既要按日期分割日志文件,又要按文件大小分割。

    <appender name="DebugAppender" type="log4net.Appender.RollingFileAppender"> ...