深拷贝与浅拷贝

2、深拷贝与浅拷贝

看这一篇的时候建议先看一下上一篇关于数据类型的文章。

直接赋值

直接赋值:把对象a赋值给对象b,实际上是把对象b的地址指向对象a的对象。a与b的地址指针一样,指向同一个对象,所以修改b时,a也会跟着发生改变。注意,修改b的无论是对象属性(引用数据类型)还是非对象属性(基本数据类型),a都会跟着发生改变。

let a = {
	name:'a',
	arr:[1,2]	
}
let b = a;
b.name = 'b';
console.log(a.name);  //  b
b.arr = [1,3]
console.log(a.arr); // [1,3]

在这里插入图片描述

浅拷贝

浅拷贝:赋值对象的非对象属性,对象a与对象b的地址指针不一样,不会指向同一个对象,对象b是一个新的对象。修改b的非对象属性,a的非对象属性不会跟着变化。但是修改b的对象属性,会影响a的对象属性。这是因为,在浅拷贝时如果是非对象属性(基本数据类型),那么拷贝的是这个非对象属性的值,如果拷贝的是对象属性(引用数据类型),那么拷贝的是地址指针,所以修改b的对象属性,会影响a的对象属性。

let a = {
	name:'a',
	other:{
		arr:[1,2]	
	}
	
}
let b = Object.assign({},a);
b.name = 'b';
console.log(a.name);  //  a
b.other.arr = [1,3]
console.log(a.other.arr); // [1,3]

在这里插入图片描述

浅拷贝实现方法

注意如果object只有一层那么就是深拷贝。

1)Object.assign()

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。例子可以看上面。

2)引用复制
function shallowClone(copyObj){
	var obj = {}
	for(let i in copyObj){
		obj[i] = copy[i]
	}
	return obj
}
3)Array.prototype.concat()
let a = [1,2,{name:'a'}]
let b = a.concat()
4)Array.prototype.slice()
let a = [1,2,{name:'a'}]
let b = a.slice()
深拷贝

深拷贝:拷贝一个一模一样的对象,对象a与对象b的地址指针不一样,不会指向同一个对象,对象b是一个新的对象,而且对象b与对象a不再共享内存。**无论修改b的非对象属性还是对象属性,a的非对象属性/对象属性都不会跟着变化。**这是因为对象b的对象属性与a对象的对象属性都不再指向同一个对象,即地址指针不一样。

let a = {
	name:'a',
	other:{
		arr:[1,2]	
	}
	
}
let b = JSON.parse(JSON.stringify(a));
b.name = 'b';
console.log(a.name);  //  a
b.other.arr = [1,3]
console.log(a.other.arr); // [1,2]

在这里插入图片描述

深拷贝实现方法
1) JSON.parse(JSON.stringify())

用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。

弊端:
1、如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
2、如果obj里有RegExp、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,symbol,则序列化的结果会把函数或 undefined,symbol丢失
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null;
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor
6、如果对象中存在循环引用的情况也无法正确实现深拷贝;

详情可见:关于JSON.parse(JSON.stringify(obj))实现深拷贝应该注意的坑

2) 递归拷贝
 function deepCopy(obj) {
	  if (obj=== null) return null;
      if (typeof obj!== 'object') return obj;
      var result = Array.isArray(obj) ? [] : {};

      for (var key in obj) {

        if (obj.hasOwnProperty(key)) {

          if (typeof obj[key] === 'object' && obj[key]!==null) {

            result[key] = deepCopy(obj[key]);   //递归拷贝

          } else {

            result[key] = obj[key];

          }

        }

      }

      return result;

    }  
3)函数库lodash
var lodash = require('lodash');
var obj1 = {
   a: 1,
   b: { b: { b: 1 } },
   c: [1, 2, 3]
};
var obj2 = lodash.cloneDeep(obj1);
console.log(obj1.b.f === obj2.b.f);
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值