【javascript】深拷贝和浅拷贝

浅拷贝: 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。(使用栈中的地址,而非堆中的数据)
深拷贝:深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。(使用堆中的数据,而非栈中的地址)

深拷贝的方法:
1. JSON方法

var obj1 = {
   name: 'shen'
}
var obj2 = JSON.parse(JSON.stringify(obj1))
obj2.name = 'shenzhiyong'

console.log('obj1:', obj1)   // obj1: {name: "shen"}
console.log('obj2:', obj2)   // obj2: {name: "shenzhiyong"}

优点:简单明了,方便记忆
缺点:无法实现对象中方法的深拷贝。看下面代码。

var obj1 = {
    name: 'shen',
    show: function (argument) {
        console.log(1)
    }
}
var obj2 = JSON.parse(JSON.stringify(obj1))
console.log('obj1:', obj1)  // obj1: {name: "shen", show: ƒ}
console.log('obj2:', obj2)  // obj2: {name: "shen"}

2. 手写递归方法

function deepCopy(obj) {
  var newobj = obj.constructor === Array ? [] : {};
  if (typeof obj !== 'object') {
    return obj;
  } else {
  for (var i in obj) {
    if (typeof obj[i] === 'object'){ //判断对象的这条属性是否为对象
      newobj[i] = deepCopy(obj[i]);  //若是对象进行嵌套调用
    }else{
        newobj[i] = obj[i];
        }
    }
    }
    return newobj; //返回深度克隆后的对象
}

var obj1 = {
    name: 'shen',
    show: function (argument) {
        console.log(1)
    }
}
var obj2 = deepCopy(obj1)
console.log('obj1:', obj1)  // obj1: {name: "shen", show: ƒ}
console.log('obj2:', obj2)  // obj2: {name: "shen"}

优点:能够实现对象和数组的深拷贝
缺点:如果拷贝的对象嵌套过深的话,会对性能有一定的消耗

3. 第三方库 jQuery.extend 和 lodash

$.extend( true, object1, object2 ); // 深度拷贝
$.extend( object1, object2 );  // 浅拷贝


var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); // => false

4. es6解析结构 「…」

var obj1 = {
    name: 'shen',
    show: function (argument) {
        console.log(1)
    }
}
var obj2 = { ...obj1 }
obj2.name = 'shenzhiyong'
console.log('obj1:', obj1)  // obj {name: "szy", show: ƒ}
console.log('obj2:', obj2)   // obj2 {name: "shenzhiyong", show: ƒ}

5. Object.assign()
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。

语法
Object.assign(target, ...sources);
参数:
target: 目标对象
sources: 源对象
返回值:
*目标对象
案例:
var obj1 = {
    name: 'shen',
    show: function (argument) {
        console.log(1)
    }
}
var obj2 = Object.assign({} ,obj1)     // 一定要写target
obj2.name = 'shenzhiyong'
console.log('obj1:', obj1)  // obj {name: "szy", show: ƒ}
console.log('obj2:', obj2)   // obj2 {name: "shenzhiyong", show: ƒ}

注意:
对于Object.assign()而言,如果对象的属性值为简单类型(string,number),通过Object.assign({},srcobj);得到的新对象为深拷贝;
如果属性值为对象或其他引用类型,那对于这个对象而言其实是浅拷贝的,这是Object.assign()特别需要注意的地方;
对象只有一级属性为深拷贝,二级属性后就是浅拷贝。

6. 数组中的slice() & concat()

var arr1 = [1,2,3]
var arr2 = arr1.slice()  // 方法一
// var arr2 = arr1.concat()  //方法二
arr2.push(4)
console.log('arr1:', arr1)  // arr1: [1, 2, 3]
console.log('arr2:', arr2)  // arr1: [1, 2, 3, 4]

注意:
数组中元素为一维是深拷贝,二维后就是浅拷贝。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值