深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。
代码中理解...
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>clone</title>
</head>
<body>
</body>
<script>
let obj={
name:"盖伦",
sex:"男",
ability:["沉默","转圈圈"]
}
var obj1 = Object.assign({},obj)
var obj2 = {...obj}
obj.sex="女"
obj.ability.push("大宝剑")
console.log(obj)
console.log(obj1)
console.log(obj2)
</script>
</html>
上面代码运行结果:
可以看出浅拷贝当属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。
深拷贝实现的目的就是是指新对象和原对象的属性值其指向的不是同一块内存地址。
实现方案1:JSON.parse(JSON.stringify(obj))
修改上面的代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>clone</title>
</head>
<body>
</body>
<script>
let obj={
name:"盖伦",
sex:"男",
ability:["沉默","转圈圈"]
}
var obj1 = Object.assign({},obj)
var obj2 = {...obj}
var obj3 = JSON.parse(JSON.stringify(obj))
obj.sex="女"
obj.ability.push("大宝剑")
console.log(obj)
console.log(obj1)
console.log(obj2)
console.log(obj3)
</script>
</html>
结果:
可以看出obj 和 obj3的值互不影响。不过这样实现有一些缺点:
对象的属性值是函数时,无法拷贝。
原型链上的属性无法拷贝
不能正确的处理 Date 类型的数据
不能处理 RegExp
会忽略 symbol
会忽略 undefined
那么自己怎么实现一个deepClone呢?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>clone</title>
</head>
<body>
</body>
<script>
let obj={
name:"盖伦",
sex:"男",
ability:["沉默","转圈圈"]
}
var obj1 = Object.assign({},obj)
var obj2 = {...obj}
var obj3 = JSON.parse(JSON.stringify(obj))
var obj4 = deepClone(obj)
obj.sex="女"
obj.ability.push("大宝剑")
console.log(obj)
console.log(obj1)
console.log(obj2)
console.log(obj3)
function deepClone(obj,hash = new WeakMap()){
//RegExp
if(obj instanceof RegExp ){
return new RegExp(obj)
}
//Date
if(obj instanceof Date){
return new Date(obj)
}
//非复杂数据类型
if(obj===null || typeof obj !=='object'){
return obj
}
if(hash.has(obj)){
return hash.get(obj)
}
let t = new obj.constructor()
hash.set(obj,t)
for(let key in obj){
if(obj.hasOwnProperty(key)){
t[key]=deepClone(obj[key],hash)
}
}
return t
}
console.log(obj4)
</script>
</html>
资料参考:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/assign