深拷贝与浅拷贝(原理+手撕的几种方法)

深拷贝与浅拷贝(原理+手撕的几种方法)

  • 深拷贝与浅拷贝(原理+手撕的几种方法)
    • 原理
    • 手撕深拷贝
      • 手撕深拷贝: 序列化和反序列化
      • 手撕深拷贝:递归

深拷贝与浅拷贝(原理+手撕的几种方法)

原理

浅拷贝是指复制对象的引用,本质上它俩共享了同一个内存空间,深拷贝是完全复刻了原对象的引用内容,并且新开辟了内存空间,用于存储这些引用。

手撕深拷贝

手撕深拷贝: 序列化和反序列化

实现过程:

  1. 把原对象转换成字符串,使用JSON.stringify方法进行序列化。
  2. 把序列化字符串解析成新的对象,使用JSON.parse方法进行反序列化。
    如此即可得到新内存空间也就是深拷贝对象。

序列化是指将一个对象转换成字符串或字节流。

let A={a:'1',b:'2'}
let c=JSON.parse(JSON.stringify(A))

注意:
对象中的所有属性必须是可以序列化的,如正则表达式、函数、Date是不能被序列化的。
在处理循环引用,需要有处理无限递归的逻辑,否则会报错。或者用circular-jsonflatted第三方库也可以解决。循环引用举例;

let A={a:'1',b:'2'}
let B={a:'1',b:'2'}
 A.a=B;
 B.b=A;
let c=JSON.parse(JSON.stringify(A))

手撕深拷贝:递归

实现过程:

  1. 创建函数,一个形参,用于传递要递归的原始对象
  2. 利用typeof判断传入对象是否为null或非object类型,如果是则直接返回原对象无需进行迭代操作。
  3. 如果不是,定义一个let变量,用isArray判断其是否为数组对象。
  4. 是则对该对象初始化为[],并用for循环进行迭代,具体在循环中利用索引值进行迭代。迭代到等于该形参长度。
  5. 不是则对该对象初始化为{},并用for in 迭代。
  6. 最终返回全新的对象。
function deepCopy(obj){
	if(obj === null || typeof obj !== 'object'){
		return obj;
	}
	let newobj;
	if(Array.isArray(obj)){
		newobj=[];
		for(let i=0;i<obj.length;i++){
			newobj[i]=deepCopy(newobj[i])
		}
	}else{
		newobj={};
		for(let key in obj){
			newobj[key]=deepCopy(obj[key])
		}
	}
	return newobj;
}

其他方法能实现单层属性深拷贝,如:Object.assign({},obj)、{...obj}。多层就不行了。
单层就是{a:1}
多层就是{a:{b:1}}。

你可能感兴趣的:(JavaScript,前端,javascript,迭代加深,性能优化)