zoukankan      html  css  js  c++  java
  • jquery的2.0.3版本源码系列(4):285-348行,extend方法详解

    目录

    1 . jquery extend的基本使用

     通过285行的源码 jQuery.extend = jQuery.fn.extend = function() { ,extend方法要么是直接挂在到jQuery的静态方法,要么是挂载到fn上其实就是原型上(参考283行的赋值操作)的实例方法。extend方法可以传一个对象,类似于插件的方式,也可以传多个对象进行拷贝。

    <script src="js/jquery-2.0.3.js"></script>
        <script>
            $.extend({
                aaa:function(){
                    alert("1");
                },
                bbb:function(){
                    alert("2");
                }
            })
            $.fn.extend({
                aaa:function(){
                    alert("3");
                },
                bbb:function(){
                    alert("4");
                }
            })
            $.aaa();//弹出1,静态方法可以直接调用
            $().aaa();//弹出3,绑定到fn上的方法,以对象的形式调用
            //多个对象参数,后面的对象会扩展到第一个对象上
            var a={};
            $.extend(a,{color:'#f40'});
            console.log(a);//color所在的对象就被扩展到a对象上
        </script>

    接下来关注extend的拷贝分深拷贝和浅拷贝。

    <script src="js/jquery-2.0.3.js"></script>
        <script>
            var a={};
            var b={name:"hello"};
            var c={name:"hello-1"};
            var d={name:{age:20}};
            var e={name:{age:50}};
            //浅拷贝对象b
            $.extend(a,b);
            a.name="hi";
            alert(b.name);//弹出hello
            //浅拷贝对象d
            $.extend(a,d);
            a.name.age=30;
            alert(d.name.age);//弹出30
            //深拷贝对象c
            $.extend(true,a,c);
            a.name="hi";
            alert(c.name);//弹出hello-1
            //深拷贝对象e
            $.extend(true,a,e);
            a.name.age=40;
            alert(e.name.age);//弹出50
        </script>

    2.代码简化版本

    分为5个部分:

    定义了一些变量

    if(){}  是不是深拷贝

    if(){}  参数正确不

    if(){}  看是不是插件的情况,插件的话传入一个含有方法的json对象

    for   传入多个对象的情况

          if防止循环应用,if深拷贝,else if浅拷贝。

    详解篇:3.1 定义了一些变量

    var options, name, src, copy, copyIsArray, clone,
            target = arguments[0] || {},
            i = 1,
            length = arguments.length,
            deep = false;

    这里要说明一下target。它就是 $.extend(a,d); 拷贝的目标对象a。这里的arguments是javascript的内置对象,是一个类数组,索引为0的值当然是参数a。

    详解篇:3.2 看是不是深拷贝

    // 处理深拷贝的情形
        if ( typeof target === "boolean" ) {
            deep = target;
            target = arguments[1] || {};
            // 如果传入的第一个参数为true,那么deep就置为true了。target目标对象就调整为第二个。
           //跳过布尔值和target
            i = 2;
        }

    这里处理的是传入了true的情况,比如 $.extend(true,a,c); 。

    详解篇:3.3 要传正确的的参数

    // 如果传进来的并非object同时也不是function,那么target置为空对象。
        if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
            target = {};
        }

    详解篇:3.4 处理插件的情形

    // 如果传进来一个参数,那么target目标对象就为jquery自己。
        if ( length === i ) {
            target = this;
            --i;
        }

    详解篇:3.5 传入多个对象的操作

    基本思路是通过arguments进行取值,获取到每个非目标对象的参数。非target对象通过in循环,获取到属性名。

    总体特征是浅拷贝只能拷贝一层,深拷贝可以连嵌套子对象也能拷贝进去。

    浅拷贝的情况下,那么走的是else分支,对相应的值进行覆盖  target[ name ] = copy; 。可以看到如果原来有target有相同的属性,那么就覆盖,如果没有,那么就添加上。

    <script src="js/jquery-2.0.3.js"></script>
        <script>
            var a={name:{age:20}};
            var b={name:{age:50}};
            //浅拷贝对象b
            $.extend(false,a,b);
            console.log(a);//{name:{age:20}}
            console.log(b);//{name:{age:50}}
        </script>

    它遇到对象嵌套,copy这里是{age:50},通过简单的赋值是修改不了的。

    <script>
            var a={name:{age:20}};
            var b={name:{age:50}};
            a[name]=b[name];
            console.log(a);//{name:{age:20}},没有变化哦。
        </script>

    深拷贝的情况下。copy是数组,src也为数组赋值给clone否则为空数组。copy是对象,src是对象赋值给clone否则为空对象。

    <script src="js/jquery-2.0.3.js"></script>
        <script>
            var a={name:{age:20}};
            var b={name:{age:50}};
            //浅拷贝对象b
            $.extend(true,a,b);
            console.log(a);//{name:{age:50}}
            console.log(b);//{name:{age:50}}
        </script>

    深拷贝的copy等于{age:50},src等于{age:20}。那么通过克隆的方式就可以把copy给到src。这其实是一个递归调用,所以深拷贝会拷贝到底。

    for ( ; i < length; i++ ) {
            // 处理非空或者没有定义的情况
            if ( (options = arguments[ i ]) != null ) {
                // 扩展基础对象,in语法把属性值取出来
                for ( name in options ) {
                    src = target[ name ];
                    copy = options[ name ];
    
                    // 防止无限循环,类似$.extend(a,{name:a})。那么如果拷贝的某一个值就等于target那么就终止代码在继续循环
                    if ( target === copy ) {
                        continue;
                    }
    
                    // 深拷贝和copy存在,以及copy要么是对象、要么是数组
                    if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
                        if ( copyIsArray ) {
                            copyIsArray = false;
                            clone = src && jQuery.isArray(src) ? src : [];
    
                        } else {
                            clone = src && jQuery.isPlainObject(src) ? src : {};
                        }
    
                        // 不移动原对象,克隆他们。
                        target[ name ] = jQuery.extend( deep, clone, copy );
    
                    // Don't bring in undefined values
                    } else if ( copy !== undefined ) {
                        target[ name ] = copy;
                    }
                }
            }
        }
  • 相关阅读:
    python中创建列表、元组、字符串、字典、集合
    python中字典的键不允许重复
    python中生成字典
    python中实现列表元素的倒序排列
    python中实现字典的逆向排列
    python中增加字典的键值对(项)、修改键值对的值
    python中访问字典
    Fortran 2003:完美还是虚幻?(节选)
    感谢裘宗燕老师!
    “符号化”的效用和缺失
  • 原文地址:https://www.cnblogs.com/chenmeng2062/p/7454225.html
Copyright © 2011-2022 走看看