美文网首页Js面试
js数组和对象的深拷贝

js数组和对象的深拷贝

作者: 北风吹_yfy | 来源:发表于2020-12-13 21:33 被阅读0次

    深浅拷贝区别:

    浅拷贝是拷贝一层,深层次的对象级别的就只拷贝引用;
    深拷贝是拷贝多层,每一级别的数据都会拷贝出来。

    在JS中,一般赋值语句=表示的只是对象/数组的引用,属于浅拷贝,浅拷贝会导致新数组和旧数组共用同一块内存地址,其中一个数组变化,另一个数组也会相应的变化。以下是我积累的一些关于对象/数组深拷贝的方法。

    一维数组的拷贝

    (1)slice()

    arrayObject.slice(start,end)
    返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。

    let arr = ['old', 1, 2, 3, 4];
    let new_arr = arr.slice();
    new_arr[0] = 'new';
    
    console.log(arr) // ["old", 1, 2, 3, 4]
    console.log(new_arr) // ["new", 1, 2, 3, 4]
    

    (2)concat()

    arrayObject.concat(arrayX,arrayX,......,arrayX)
    方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
    该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。

    let arr = ['old', 1, 2, 3, 4];
    let new_arr = arr.concat();
    new_arr[0] = 'new';
    
    console.log(arr) // ["old", 1, 2, 3, 4]
    console.log(new_arr) // ["new", 1, 2, 3, 4]
    

    (3)Object.assign() 数组/对象都可

    该方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。我们可以使用它进行对象的复制、合并。

    // 复制
    let c = Object.assign({}, { a: 'apple' });
    console.log(c); // { a: 'apple' }
    
    //合并
    let o = {}
    let c = Object.assign(o, { a: 'apple' }, { b: 'banana' }, { c: 'cake' } )
    console.log(c) // { a: 'apple', b: 'banana', c: 'cake' }
    

    虽然它可以复制对象,但是 Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。

    (4)ES6扩展运算(...)数组/对象都可

    let arr =  ["a", "b"] ;
    let arrCopy = [...arr];
    arrCopy[1] = "c";
    arr   // => ["a", "b"] 
    arrCopy   // => ["a", "c"]
    

    以上四个个方法 concat、slice、JSON.stringify,... 都算是技巧类,可以根据实际项目情况选择使用,接下来我们实现多维数组/对象的深拷贝。

    多维数组的拷贝

    (1)封装方法

    let obj1 = {
           a: '1',
            b: '2',
            c: {
                     d: '3'
                 },
             d: function aa() {}
       }
    
        function deepCopy(obj) {
              if(typeof obj !== 'object') return;
              let newObj = obj instanceof Array ? [] : {};
              for(var key in obj) {
                   if(obj.hasOwnProperty(key)) {
                        newObj[key] = typeof obj[key] === 'object' ? deepCopy(obj[key]) : obj[key];
                    }
                }
                return newObj;
           }     
          let tes=deepCopy(obj1);
          console.log(tes)
          obj1.c.d=32;
          console.log(obj1)
    

    (2)JSON.parse() & JSON.stringify() (推荐)

    原理:实现对象的深拷贝(利用JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象)

    let arr =  ["a", "b"] ;
    let arrCopy = JSON.parse(JSON.stringify(arr));
    arrCopy[1] = "c";
    arr   // => ["a", "b"] 
    arrCopy   // => ["a", "c"]
    

    (3)lodash

    使用第三方的库进行深拷贝:lodash
    该函数库也有提供_.cloneDeep用来做 Deep Copy

    var _ = require('lodash');
    var obj1 = {
        a: 1,
        b: { f: { g: 1 } },
        c: [1, 2, 3]
    };
    var obj2 = _.cloneDeep(obj1);
    console.log(obj1.b.f === obj2.b.f);  // false
    

    相关文章

      网友评论

        本文标题:js数组和对象的深拷贝

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