• 真正的Javascript深拷贝(不仅拷贝多个层级的值,还拷贝了类型)


    参考文章:

    1、js如何判断一个对象是不是Array?

    2、实现JS数组的深拷贝

    参考文章2的深拷贝代码如下:

    function getType(o)
        {
            var _t;
            return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase();
        }
        function extend(destination,source)
        {
            for(var p in source)
            {
                if(getType(source[p])=="array"||getType(source[p])=="object")
                {
                    destination[p]=getType(source[p])=="array"?[]:{};
                    arguments.callee(destination[p],source[p]);
                }
                else
                {
                    destination[p]=source[p];
                }
            }
        }
        var test={a:"ss",b:"dd",c:{d:"css",e:"cdd"}};
        var test1={};
        extend(test1,test);
        test1.c.d="change"; //改变test1的c属性对象的d属性
        alert(test.c.d);  //不影响test
    

      假如:

    var test={a:"ss",b:"dd",c:{d:"css",e:"cdd"}};
    var test1=[];//使用该方法深拷贝,必须先定义拷贝到的对象,并且初始化
    extend(test1,test);
    test1.c.d="change"; //改变test1的c属性对象的d属性
    alert(test.c.d);  //不影响test
    这样做,的确也把test的数据复制过来了,而且,修改test1.c.d也不会对test造成影响,但是接下来的问题来了,test1的类型改变了,这个时候,我们按照原类型去处理,比如使用array的push方法,就会出错了,chrome监视情况如下
    代码:

    Chrome对象监视

    无废话,正确代码如下
    
    

    Ext.namespace("GTP.BI");
    GTP.BI.Util = {};

    GTP.BI.Util.getType = function (o) {

        var _t;
        return ((_t = typeof (o)) == "object" ? o == null && "null" || Object.prototype.toString.call(o).slice(8, -1) : _t).toLowerCase();
    };
    
    GTP.BI.Util.copy = function (source) {
        var destination = GTP.BI.Util.getType(source) == "array" ? [] : {}; //呵呵,联想到了Ext.extend方法
        for (var p in source) {
            if (GTP.BI.Util.getType(source[p]) == "array" || GTP.BI.Util.getType(source[p]) == "object") {
                destination[p] = GTP.BI.Util.getType(source[p]) == "array" ? [] : {};
                destination[p] = arguments.callee(source[p]);
            }
            else {
                destination[p] = source[p];
            }
        }
        return destination;
    }


    var test = { a: "ss", b: "dd", c: { d: "css", e: "cdd"} };
    var test1 = [];
    test1 = GTP.BI.Util.copy(test);
    test1.c.d = "change"; //改变test1的c属性对象的d属性
    alert(test.c.d); //不影响test

    重要说明:test1 此时也为Object,它和初始化类型毫无关系。其实这里根本就不需要初始化,当然,若是初始化了,在这里不仅深拷贝了值,而且也拷贝了类型,将test1的初始化值和类型完全覆盖(这样的才是深拷贝么,哇哈哈)。

    相对于参考文章二,其实做出的修改很小,主要是添加了命名空间(使用Extjs),另外,改了一下函数,在实现拷贝的时候,不需要传入要拷贝到的地方(destination),而采取动态生成destination对象,解决使用参考文章2中以下问题:

    1、拷贝时需要初始化destination类型

    2、若初始化错destination类型,会导致拷贝后类型变化的问题。

  • 相关阅读:
    送走2015,迎来2016
    Android-Volley网络通信框架(StringRequest & JsonObjectRequest)
    Mac上配置 Ruby on Rails和Git
    学习Javascript闭包(Closure)
    cocos2d-x 学习资源整理(持续更新...)
    android自己定义刷新类控件
    awk条件语句
    Leetcode 236 Lowest Common Ancestor of a Binary Tree
    Linux查看当前正在执行的进程
    Thinking in UML 学习笔记(三)——UML核心视图之类图
  • 原文地址:https://www.cnblogs.com/piaolingzxh/p/2595794.html
Copyright © 2020-2023  润新知