js中的深克隆(深拷贝)和浅克隆(浅拷贝)

浅克隆:直接将存储在中的值赋值给对应变量,如果是基本数据类型,则直接赋值对应的值,如果是引用类型,则赋值的是地址

基本数据类型是直接存储在栈内存中的,而引用数据类型,则仅仅是把地址存储在栈内存中,真正的数据是存储在堆内存中的,赋值操作时,仅仅把地址进行了赋值。

深克隆:就是把数据赋值给对应的变量,是拷贝对象各个层级的属性,在内存中开辟一块新内存,将原对象中的所有值全部复制过去,与原对象完全脱离,修改新对象中的属性值不会影响原对象、

浅克隆举例

let a = "xu";
let b = a;
alert( b ); // 'xu'
a = "ke";
alert( b ); // 'xu'

// 在这段代码中,把a赋值给b,当a的值发生变化时,并不影响b


let arr1 = [1, 2, 3];
let arr2 = arr1;
console.log( arr2 );  // [ 1, 2, 3]
arr1[0] = 2;
console.log( arr2 );  // [ 2, 2, 3]

// 在这段代码中,把arr1赋值给arr2,当arr1的值改变时,arr2对应的值也会改变



浅克隆实现方法:
  1. es6 拓展运算符
const obj ={
     
	name:"xuke",
	age:22
}
const obj2 = {
     ...obj}
console.log(obj2.name) //xuke
  1. for循环遍历
let obj = {
     
	name:"xuke",
	age:22
}
function clone(obj ){
     
	const result = {
     }
	for(let key in obj){
     
		result[key] = obj[key];
	}
	return result 
}
let obj2 = clone(obj)
obj.name = "xiannv"
console.log(obj2.name) //xuke
console.log(obj2==obj) //false

obj2不会受obj的影响,因为被克隆的都是·基本数据类型,被存到中的东西,

如果obj中存在引用数据类型的话:

let obj ={
     
	name:"xuke",
	age:22,
	hobby:{
     
		first:"eat",
		second:"sleep"
	}
	
}
function clone(obj ){
     
	const result = {
     }
	for(let key in obj){
     
		result[key] = obj[key];
	}
	return result 
}
let obj2 = clone(obj)
obj.hobby.first= "play"
console.log(obj2.hobby.first) //play
console.log(obj2==obj) //false

我们可以看到obj2复制的obj中含有引用数据类型,我们修改了obj中的引用数据类型时,obj2中的也会改变,数据在复制的时候是把obj中的引用数据类型地址一起复制过去了,所以objobj2使用的是一个地址,所以obj2会受影响,我们想要不受影响就要使用深克隆的方法。

深克隆实现方法:
  1. JSON.parse(JSON.stringify())实现深度克隆
let obj ={
     
	name:"xuke",
	age:22,
	hobby:{
     
		first:"eat",
		second:"sleep"
	}
}

let obj2 = JSON.parse(JSON.stringify(obj))
obj.hobby.first= "play"
console.log(obj2.hobby.first) //eat
console.log(obj2==obj) //false

JSON.parse(JSON.stringify())实现深度克隆的弊端:

1.对象中的方法不能进行copy,会自动忽略
2.对象中的Date时间不能进行copy, JSON.stringify方法会将日期自动转换为常规日期格式

3.正则表达式不能copy , JSON.stringify方法会将正则变为空对象

解决方法,用方法2将这些过滤掉:
2. 用递归实现深克隆

let obj ={
     
	name:"xuke",
	age:22,
	hobby:{
     
		first:"eat",
		second:"sleep"
	}
}
function clone(obj ){
     
	// 过滤特俗情况
	if(obj===null) return obj
	if(typeof obj !=='object') return obj
	if(obj instanceof RegExp){
     
		return new RegExp(obj)
	}
	if(obj instanceof Date){
     
		return new Date(obj)
	}
	let newObj = new obj.constructor
	for(let key in obj){
     
		if (obj.hasOwnProperty(key)) {
     
			newObj[key] = clone(obj[key] )
		}
	}
	return newObj 
}
let obj2 = clone(obj)
obj.hobby.first= "play"
console.log(obj2.hobby.first) //eat
console.log(obj2==obj) //false

使用:当copy源中没有引用类型,方法,正则,日期等值,只是普通的数据类型时,我们就可以用浅拷贝的方法,反之用深拷贝

你可能感兴趣的:(javascript,面试知识点)