• JS如何进行对象的深克隆(深拷贝)?


    JS中,一般的赋值传递的都是对象/数组的引用,并没有真正的深拷贝一个对象,如何进行对象的深拷贝呢?

    var a = {name : 'miay'};
    var b = a;
    b.name = 'Jone';
    console.log(a.name)   //Jone

    上述代码中,b指向a所指向的栈对象,也就是说a,b指向同一个栈对象,这种属于对象的浅拷贝。

    var a = {name : 'miay'};
    var b = Object.assign({},a);
    console.log(a === b)  //false
    b.name = 'chris';
    console.log(a.name)  //miya

    上述代码将原对象拷贝到一个空对象中,a,b指向的是不同的栈对象,所以对b.name重新赋值不会影响到a.name,但是如果a.name是一个对象的引用,而不是一个字符串,那么a.nam和b.name指向的栈空间就是同一个了,看下面的栗子:

    var a = {name:{firstName:"tang",lastName:"jiao"}}
    var b = Object.assign({},a)
    console.log(a === b);  //false
    b.name.firstName = "chen"
    console.log(a.name.firstName) //chen

    可以看出,Object.assign只是介于对象的深克隆和浅克隆之间的一种拷贝。具体来说也只是浅拷贝。对于对象属性值为引用类型时,赋值时也是对于栈对象的引用罢了,那如何真正的进行对象的深拷贝呢?

    使用JSON.parse()和JSON.stringify()对对象进行深拷贝 

    var clone = function(obj){
        return JSON.parse(JSON.stringify(obj));
    }
    var a = {
        a:function(){console.log('hello world')},
        b:{c:1},
        c:[1,2,3],
        d:'tang',
        e:new Date(),
        f:null,
        g:undefined
    }
    var b = clone(a);
    console.log(b)

     

    可以看出,上述clone的方法会忽略function和undefined的字段,对date类型支持貌似也不友好。而且只能克隆原始对象自身的值,不能克隆它继承的值,参考代码如下:

    function Person(name){
        this.name = name;
    }
    var tang = new Person('miya');
    var newtang = clone(tang)
    tang.constructor === Person //true
    newtang.constructor === Person //false
    console.log(newtang.constructor)  //ƒ Object() { [native code] }

    结论:对于纯数据的json对象的深克隆,可以使用JSON.parse()和JSON.stringify()方法,自己可以写个兼容function,undefined,继承,Date的深拷贝的方法: 

    var clone = function(obj){
        if(obj === null) return null;
        if(obj.constructor !== 'object') return obj;
        if(obj.constructor === Date) return new Date(obj);
        if(obj.constructor === RegExp) return new RegExp(obj);
        var newObj = new obj.constructor(); //保持继承的原型
        for(var key in obj){
            if(obj.hasOwnProperty(key)){
                var val = obj[key];
                newObj[key] = typeof val === 'object' ? arguments.callee(val):val;
            }
        }
        return newObj;
    }

     经过验证,上述的原型的继承,还是function,undefined,日期,正则等都完美实现深拷贝!

    这里运用的就是建立一个新的对象,进行原始对象自有属性的拷贝,遇到引用类型则继续该方法的执行,非引用类型直接赋值。

    我唯一知道的就是自己的无知。【完】

    【我所知道的只有一件事,那就是我什么也不知道。】 ——苏格拉底

      [BGM] The Old Measure  ——Daniel Martin Moore

  • 相关阅读:
    [CF1166E] The LCMs Must be Large
    AtCoder Beginner Contest 161
    [CF1168B] Good Triple
    [CF1172B] Nauuo and Circle
    [CF1185E] Polycarp and Snakes
    [CF1187E] Tree Painting
    Codeforces Round #631 (Div. 2)
    [CF1200E] Compress Words
    Thinkphp绕过宝塔getshell
    如何成为一个漏洞赏金猎人
  • 原文地址:https://www.cnblogs.com/tangjiao/p/9313829.html
Copyright © 2020-2023  润新知