JavaScript深拷贝、浅拷贝

栏目: JavaScript · 发布时间: 5年前

内容简介:浅拷贝:浅拷贝只是复制了内存地址,如果原地址中的对象改变了,浅拷贝出来的对象也会相应改变。深拷贝:开辟了一块新的内存存放地址和地址指向的对象,原地址的任何对象改变了,深拷贝出来的对象不变。

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 格式的对象才可以这样用,像 functionundefinedsymbol 、循环引用的对象没办法转成 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
}

JavaScript深拷贝、浅拷贝


以上所述就是小编给大家介绍的《JavaScript深拷贝、浅拷贝》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

阿里巴巴Java开发手册

阿里巴巴Java开发手册

杨冠宝 / 电子工业出版社 / 2018-1 / 35

《阿里巴巴Java开发手册》的愿景是码出高效,码出质量。它结合作者的开发经验和架构历程,提炼阿里巴巴集团技术团队的集体编程经验和软件设计智慧,浓缩成为立体的编程规范和最佳实践。众所周知,现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程相关的知识点,其他维度的知识点也会影响软件的最终交付质量,比如,数据库的表结构和索引设计缺陷可能带来软件的架构缺陷或性能风险;单元测试的失位导致集......一起来看看 《阿里巴巴Java开发手册》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具