美文网首页
对象的深拷贝和浅拷贝

对象的深拷贝和浅拷贝

作者: 颠倒的黑白 | 来源:发表于2017-06-21 17:21 被阅读0次

    数组的深浅拷贝

    在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份,事实证明如果只是简单的将它赋予其他变量,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致了问题的发生。

    浅拷贝
    var arr = ["One","Two","Three"];
    console.log(arr);//["One", "Two", "Three"]
    
    var arrto = arr;
    arrto[1] = "test";
    console.log("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,test,Three
    console.log("数组的新值:" + arrto + "<br />");//Export:数组的新值:One,test,Three
    

    像上面的这种直接赋值的方式就是浅拷贝,很多时候,这样并不是我们想要得到的结果,其实我们想要的是arr的值不变,不是吗?

    深拷贝

    方法一:js的slice函数

    var arr = ["One","Two","Three"];
    
    var arrtoo = arr.slice(0);
    arrtoo[1] = "set Map";
    document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
    document.writeln("数组的新值:" + arrtoo + "<br />");//Export:数组的新值:One,set Map,Three
    

    方法二:js的concat方法

    var arr = ["One","Two","Three"];
    
    var arrtooo = arr.concat();
    arrtooo[1] = "set Map To";
    document.writeln("数组的原始值:" + arr + "<br />");//Export:数组的原始值:One,Two,Three
    document.writeln("数组的新值:" + arrtooo + "<br />");//Export:数组的新值:One,set Map To,Three
    

    Obj的深浅拷贝

    直接引用,修改了原对象

    let conf = {
      adapter:'sqlite',
      db: {
        sqlite:{
          name:'xxx.sqlite'
        },
        mysql:{
          name:'xxx',
          username:'work',
          passwd:'******'
        }
      }
    }
    
    //直接引用
    let conf2 =conf;
    conf2.adapter = 'mysql';
    console.log(conf);
    console.log(conf2)
    

    浅拷贝

    let conf = {
      adapter:'sqlite',
      db: {
        sqlite:{
          name:'xxx.sqlite'
        },
        mysql:{
          name:'xxx',
          username:'work',
          passwd:'******'
        }
      }
    }
    
    //浅拷贝
    let copied = Object.assign({},conf);
    copied.adapter = 'mysql';
    console.log(conf.adapter);//"sqlite"
    console.log(copied.adapter);//"mysql"
    copied.db.sqlite.name ='yyy.sqlite';
    //多级属性无法被拷贝,而是引用
    console.log(conf.db.sqlite.name);//"yyy.sqlite"
    console.log(copied.db.sqlite.name);//"yyy.sqlite"
    

    所以使用深拷贝

    let conf = {
     adapter:'sqlite',
     db: {
       sqlite:{
         name:'xxx.sqlite'
       },
       mysql:{
         name:'xxx',
         username:'work',
         passwd:'******'
       }
     }
    }
    
    //深拷贝
    function deepCopy(des,src) {
     for(var key in src) {
       let prop = src[key];
       if (typeof prop === 'object') {
         des[key] = des[key]||{}; //判断目标对象是否有自身的key
         deepCopy(des[key],prop);
       }else{
         des[key] = src[key];
       }
     }
     return des;
    }
    
    let obj1= {
     db:{
       c:"name"
     },
     ad:'ad'
    }
    
    
    let deepCopied = deepCopy(obj1,conf);
    let deepCopied2= deepCopy({},conf);
    console.log(deepCopied);
    console.log(deepCopied2);
    deepCopied.db.sqlite.name = 'zzz.sqlite';
    console.log([deepCopied.db.sqlite.name,conf.db.sqlite.name]);
    
    //console
    [object Object] {
     ad: "ad",
     adapter: "sqlite",
     db: [object Object] {
       c: "name",
       mysql: [object Object] { ... },
       sqlite: [object Object] { ... }
     }
    }
    [object Object] {
     adapter: "sqlite",
     db: [object Object] {
       mysql: [object Object] { ... },
       sqlite: [object Object] { ... }
     }
    }
    ["zzz.sqlite", "xxx.sqlite"]
    

    相关文章

      网友评论

          本文标题:对象的深拷贝和浅拷贝

          本文链接:https://www.haomeiwen.com/subject/vistcxtx.html