<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>深克隆</h1>
</body>
<script>
var obj = {
name:"小罗",
age:22
}
function deep(data) {
var datatype = Object.prototype.toString.call(data);
console.log(datatype);//object.prototype.toString.call()判断类型。
if (datatype == ['object Array']) { //判断是否为数组
var arr1 = [];//定义空数组
// 参数 foreach 函数a 空数组.push(deep[a])
data.forEach(function (a) {
arr1.push(deep[a])
})
return arr1//返回空数组
} else if (datatype == '[object Object]') {//判断是否为对象
var obj = {} //定义空对象
for (key in data) { //for(key in data){空对象[key] = 方法名deep(data[key])输出空对象[key]}
obj[key] = deep(data[key])
console.log(obj[key]);
}
return obj //返回空对象
} else {
return data//返回基本类型
}
}
var obj1 = deep(obj);
obj1.name = "小红"
console.log(obj);
console.log(obj1);
</script>
</html>
1、 回顾基本类型和引用类型赋值过程
- 基本类型:按值传递
- 引用类型:按址传递
浅拷贝:拷贝一个新对象还是与旧对象共享指向同一块内存空间,造成的问题是修改新对象的值会直接影响到旧对象。
深拷贝:完全在堆中开辟一个新的内存空间去存储拷贝后的新对象,新旧内存空间都是独立的,修改新对象不会影响旧对象。
实现浅拷贝(只拷贝第一层)
- 通过lodash函数库的
_.clone(value)实现,创建一个 value 的浅拷贝(只拷贝第一层) - 或通过
Object.assign()实现 - 或通过展开运算符
{...obj}来实现
实现深拷贝(递归拷贝)
- 利用lodash工具库的_.cloneDeep(value) : 递归拷贝 value。(注:也叫深拷贝)。
- 手动封装递归函数实现
总而言之,浅拷贝只复制指向某个对象的内存地址(指针),而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,且新对象跟旧对象不共享内存,修改新对象不会影响旧对象。
注意 :通过JSON.stringify可以对简单的对象进行深拷贝,后续再用JSON.parse函数反转回来即可。
但是它有缺点,一些特殊的值会丢失,
-
binInt类型的值无法转化;如 10n
-
对于属性值类型是
undefined、function、symbol等类型,会丢失对应值选项 -
对于属性值类型是
err、regexp 这些类型,属性值会变为空对象。 -
对于属性值类型是
date等类型,属性值会变为字符串。即使再次转回对象,属性值还是字符串。