zoukankan      html  css  js  c++  java
  • jQuery原型方法.pushStack源码分析

    这次分析的方法跟前面不同,虽然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只能做一个幕后英雄啦

  • 相关阅读:
    windows下mysql数据库导入导出
    比较两个数组,根据id删除相同的对象
    angular子组件给父组件传值
    angular父组件给子组件传值
    angular获取dom节点
    angular创建服务
    forEach和for包含异步调用的区别
    用某种符号或字符替换某些字符
    嵌套函数和闭包
    JavaScript 递归
  • 原文地址:https://www.cnblogs.com/yy-hh/p/4636106.html
Copyright © 2011-2022 走看看