WHAT?
说到深浅拷贝我们必须简单了解JavaScript基本数据类型和引用数据的区别
赋值
基本数据类型
//在栈内开辟一个空间,空间名称叫a,存放值1;
let a = 1;
//在栈内开辟一个空间,空间名字叫b
//接着先把a的值1复制一份,然后存放进b
let b = a;
a=3;
console.log(b)//1
引用数据类型
//首先在栈开辟一个空间a存放指针地址,设指针地址为address1;同时会在堆里面开辟一个空间放置对象数据
let a = {
name: "Jack"
}
//a赋值给b,此时b会在栈开辟一个空间b,用来放置address1,这个指针指向a所在堆的对象数据
let b = a;
//修改赋值后的值b,其实就是修改b的指针address1所指向的对象数据
b.name = "Rose";
console.log(a.name, b.name)//Rose Rose
深拷贝 浅拷贝
浅拷贝只复制指向某个对象的指针
,而不复制对象本身,新旧对象还是共享同一块内存。
深拷贝会另外创造开辟新的内存空间来储存一个一模一样的对象
,新对象跟原对象不共享内存,修改新对象不会改到原对象。
WHY?
当我们需要拷贝一份多层引用数据 如果原数据还要用来做其他事情时 就要用到深拷贝修改新数据原数据不能随之发生改变
HOW?
浅拷贝
- Object.assign()
- ES6 扩展运算符
- Array.concat()
- Array.slice()
由于比较简单这里就不一一举例了
需要注意当第一层为基本数据类型时Object.assign() 扩展运算符是深拷贝
let obj = { a: 1, arr: [1, 2] }
let newObj = Object.assign({}, obj)
newObj.a = 10
console.log(newObj.a, obj.a) //10 1
深拷贝
1 用JSON.stringify 把对象转换成字符串,再用 JSON.parse 把字符串转换成新的对象。可以转成JSON格式的对象才能使用这种方法,如果对象中包含 function 就不能用这种方法了。
let obj = { a:1, arr: [1,2] };
let newObj = JSON.parse(JSON.stringify(obj));
newObj.arr[0] = 10;
console.log(newObj.arr[0],obj.arr[0]); //10 1
2 递归深拷贝
const json = [
{
id: 1,
fn() {},
title: "课程1",
children: [
{ id: 4, title: "课程1-1" },
{
id: 5,
title: "课程1-2",
children: [
{ id: 6, title: "课程1-2-1" },
{ id: 7, title: "课程1-2-2" },
],
},
],
},
{ id: 2, title: "课程2" },
{ id: 3, title: "课程3" },
]
// 定义检测数据类型的方法
function typeCheck(data) {
return Object.prototype.toString.call(data).slice(8, -1)
}
// 递归函数
function deepClone(target) {
let type = typeCheck(target)
if (type != "Object" && type != "Array") {
return target
}
//定义数据的容器
let result = Array.isArray(target) ? [] : {}
// 循环传递过来的数据
for (let key in target) {
let value = target[key]
// 如果当前数据仍为对象或数据 将此值设为函数参数 继续拷贝否则就直接拷贝出去
typeof value === "object"
? (result[key] = deepClone(value))
: (result[key] = value)
}
return result
}
let res = deepClone(json)
res[0].fn = 111
console.log(json)
console.log(res)~~~~
人生到处知何似,应似飞鸿踏雪泥。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。