深浅拷贝的区别既处理

一、栈和堆
		概念
			栈:一般用来存变量名和地址,空间小,不可修改
			堆:一般用来存值(变量的值...如)空间大,可修改
		关系
			1.一一对应:一个栈对应一个堆
			2.多对一:多个栈对应一个堆
		存取规则
			栈:先进后出
			堆:先进先出
二、数据类型分类
			1.基本类型:
				特点:
					1. 数据存在栈中,默认深拷贝,改变新的(b)不影响老的(a)
					2. 变量名和值都存在栈中,值就是地址地址就是值
					 如:var a=10;var b=a;b=20;console.log(a)//10,console.log(b)//20
				除了对象、数组、函数都是基本类型
			引用类型
				特点:
					1.栈中只保存了地址(变量名),该地址指向堆中的某个数据(既该地址(变量名)所对应的值保存在堆中)
					2.默认浅拷贝,只复制地址(变量名,属性名),没有复制值,改变新的(o2.name)影响老的(o1.name)
					3.数组函数对象都是引用类型的数据
						var o1={name:"zhangsan"};
						var o2=o1;
						o2.name="lisi";
						console.log(o2.name) //lisi
						console.log(o1.name) //lisi
三、深浅拷贝
		浅拷贝:只复制地址(变量名)栈中存的数据
		深拷贝:既复制栈中数据也复制堆中数据
		引用数据类型如对象默认浅拷贝
			var o1={name:"zhangsan"};
			var o2=o1;
			此时o1,o2这两个栈中的数据同时指向同一个堆,(o1的{name:"zhangsan"}),
			设置o2.name="lisi"后o1,o2还是同时指向这个堆,所以原来的o1的值也被改变了
四、引用数据类型(对象,数组函数)实现深拷贝的方法
		**浅拷贝 复制的是地址而非具体的值**
	            let obj1 = { a: 1, b: 2 };
				let obj2 = obj1;
				obj2.a = 11;
				console.log(obj1);  //{ a: 11, b: 2 }
				

深拷贝的实现:通过遍历原对象拷贝地址和值放入新对象,此时obj1,obj2指向两个不同的堆,改变obj2的值不会影响obj1的值

	let obj1 = { a: 1, b: 2 };
		let obj2 = {};
		for (let i in obj1) {
			obj2[i] = obj1[i];
		}
		obj2.a = 11;
		console.log(obj1);  //{ a: 1, b: 2 }

以上存在问题:原对象的值仍然是一个引用对象时,for-in只实现了一层深拷贝,obj1和obj2指向不同的堆地址,但是他两的属性a的值仍然是共用的[1],改变obj2的a的值仍然会影响obj1的a的值

  let obj1 = { a: [1], b: 2 };
	let obj2 = {};
	for (let i in obj1) {
		 obj2[i] = obj1[i];
	}
	console.log(obj2);//{ a: [1], b: 2 }
	console.log(obj1);//{ a: [1], b: 2 }
	obj2.a[0] = 11;//会有影响
	console.log(obj1); { a: [11], b: 2 }

解决方案一
// 加判断利用递归思想,如果仍然是引用数据类型继续遍历

let obj1 = { a: [1], b: 2 };
					function deepCopy(obj) {
					  // 如果传进来的将要被拷贝的数据是数组则创建一个新的空数组
						// 注意数组instanceof检测也是对象不能判断究竟是对象还是数组,所以条件写Arraaay
					  if (obj instanceof Array) {
					    var newObj = [];
					  } else { //如果传进来的将要被拷贝的数据是对象则创建一个新的对象
					    var newObj = {};
					  }
					  
					  // 遍历旧的对象,判断如果对象的某个键对应的值的数据类型是对象,则把obj[i]作为参数再执行deepCopy(obj),
					  // 相当于遇见旧对象的值还是对象时让新的obj2的某个键(再创建一个新对象79行)再调用函数再进行一次深拷贝,依次
					  // 进行逐层进行深拷贝(递归),直到 旧对象的值的数据类型全不是object,深拷贝结束,返回新的对象
					  for (let i in obj) {
					    if (typeof obj[i] == "object") {
					      newObj[i] = deepCopy(obj[i]);
					    } else {
					      newObj[i] = obj[i];
					    }
					  }
					
					  return newObj;
					} 
					 let obj2 = deepCopy(obj1);

解决方案二

	let obj1 = { a: [1], b: 2 };
	let obj2 = JSON.parse(JSON.stringify(obj1));
	console.log(obj2);
	obj2.a[0] = 11;
	console.log(obj1);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值