• JS JavaScript深拷贝、浅拷贝


    浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。

    深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。

    浅拷贝数组(只拷贝第一级数组):

    1.直接遍历

    var arr = [1,2,3,4];
    
    
    function copy(arg){
      
      var newArr = [];
      
      for(var i = 0; i < arr.length; i++) {
        newArr.push(arr[i]);
      }
      
      return newArr;
    }
    
    var newArry = copy(arr);
    console.log(newArry);
    newArry[0] = 10;
    console.log(newArry); // [10,2,3,4]
    console.log(arr)  // [1,2,3,4]

    2.slice

    var arr = [1,2,3,4]
    var copyArr = arr.slice();
    copyArr[0] = 10;
    console.log(copyArr); // [10,2,3,4]
    console.log(arr); // [1,2,3,4]

    slice(start,end),slice()方法返回一个数组中复制出来的元素组成新数组,start指起始元素下标,end指终止元素下标

    当slice()不带任何参数时,默认返回一个和原数组一样的新数组

    3.concat()

    var arr = [1,2,3,4]
    var copyArr = arr.concat();
    copyArr[0] = 10;
    console.log(copyArr); // [10,2,3,4]
    console.log(arr); // [1,2,3,4]

    array.concat(array1,array2,.......,arrayN),concat()方法用于连接两个或多个数组(不会改变原数组,返回被连接数组的副本)

    然而如果第一级数组元素是对象或数组,上面三种方式都失效:

    var arr = [
      {number:1},
      {number:2},
      {number:3}
      
    ]
    var copyArr = arr.slice();
    copyArr[0].number = 10;
    console.log(copyArr);  // [{number: 100}, { number: 2 },{ number: 3 }]
    console.log(arr); // [{number: 100}, { number: 2 }, { number: 3 }]

    浅拷贝对象(如果对象中的值不为数组或对象)

    1.直接遍历

      var obj = {
        name: "张三",
        job: "学生"
      }
      
      function copy (arg) {
        let newobj = {}
        for(let item in obj) {
          newobj[item] = obj;
        }
        return newobj;
      }
      
      var copyobj = copy(obj)
      copyobj.name = "李四"
      console.log(copyobj) // {name: '李四', job:: '学生'}
      console.log(obj) // {name: '张三', job:: '学生'}

    2.ES6的Object.assign

    var obj = {
      name: '张三',
      job: '学生'
    }
    
    var copyobj = Object.assign({},obj)
    copyobj.name = '李四'
    console.log(copyobj) // {name: '李四', job:: '学生'}
    console.log(obj)    // {name: '张三', job:: '学生'}

    Object.assign:用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target),并返回合并后的target

    用法: Object.assign(target, source1, source2); 所以 copyObj = Object.assign({}, obj); 这段代码将会把obj中的一级属性都拷贝到 {}中,然后将其返回赋给copyObj

    3.ES6扩展运算符
    var obj = {
      name: '张三',
      job: '学生'
    }
    
    var copyobj = {...obj}
    copyobj.name = '李四'
    console.log(copyobj)
    console.log(obj)

    扩展运算符(...)用于取出参数对象的所有可遍历属性,拷贝到当前对象之中

    深拷贝

    JSON.stringify()和JSON.parse

    用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

    但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

    这种方法能正确处理的对象只有 Number, String, Boolean, Array, 扁平对象,即那些能够被 json 直接表示的数据结构。RegExp对象是无法通过这种方式深拷贝。

    也就是说,只有可以转成JSON格式的对象才可以这样用,像function、undefined、symbol、循环引用的对象没办法转成JSON。

    var obj1 = { fun: function(){ console.log(123) } };
    var obj2 = JSON.parse(JSON.stringify(obj1));
    console.log(typeof obj1.fun);
    // 'function'
    console.log(typeof obj2.fun);
    // 'undefined' <-- 没复制

    使用递归函数实现一个深拷贝的方法

    function deepClone(obj) {
        let objClone = Array.isArray(obj) ? [] : {};
        if(obj && typeof obj === "object") {
            for(key in obj) {
                if(obj.hasOwnProperty(key)) {
                    if(obj[key] && typeof obj[key] === "object") {
                        objClone[key] = deepClone(obj[key]);
                    } else {
                        objClone[key] = obj[key];    
                    }
                 }
             } 
        }
        return objClone
    }            
  • 相关阅读:
    UML建模之时序图(Sequence Diagram)
    UML统一建模语UML2和EnterpriseArchitect
    FTP服务器的搭建
    Ubuntu下Apache重启错误:Could not reliably determine解决
    JSP的优势 和劣势 与php的比较
    [置顶] Ajax 初步学习总结
    pv ticketlock解决虚拟环境下的spinlock问题
    Tomcat从零开始(十)Loader
    HDU 4740 The Donkey of Gui Zhou (模拟)
    关于cvScalar的那些事
  • 原文地址:https://www.cnblogs.com/lhh520/p/10264410.html
Copyright © 2020-2023  润新知