深拷贝和浅拷贝
说明
基本数据类型不存在深浅拷贝,因为基本类型赋值时,赋的是数据(所以,不存在深拷贝和浅拷贝的问题)
什么是深拷贝和浅拷贝?
浅拷贝:基本数据类型,拷贝的是基本数据类型的值,引用类型只是对指针的拷贝,拷贝后两个指针指向同一个内存,同一份数据,意味着当原对象发生变化的时候,拷贝对象也跟着变化;
深拷贝:不但对指针进行拷贝,而且还对指针指向的内容进行拷贝,也就是另外申请了一块空间内存,内容和原对象一致,但是是两份独立的数据,更改原对象,拷贝对象不会发生变化。
深拷贝的作用
实际开发中也是非常有用的。例如后台返回了数据,我们需要对这些数据做操作,但是这些数据可能有其它地方也需要使用,直接修改就可能会造成很多隐性问题,而把数据做一次深拷贝就能让我们更安全安心的去操作这些数据,因为反正我们复制了一份下来。
深浅拷贝的几种方式
浅拷贝
//Object.assign()
//用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象
总结:原始对象的简单数据类型值没变,复杂数据类型值改变
const obj1 = { a: 1, b: 2, c: function () { d: 1 } }
const obj2 = {}
Object.assign(obj2, obj1)
obj2.a = 2
obj2.c.d = 2
console.log(obj1.a); //1
console.log(obj1.c.d); //2
//解构赋值
总结:原始对象的简单数据类型值没变,复杂数据类型值改变
const obj1 = { a: 1, b: function () { c: 1 } }
const obj2 = { ...obj1 }
obj2.a = 2
obj2.b.c = 2
console.log(obj1.a); //1
console.log(obj1.b.c); //2
//concat()、split()、slice()
总结:原始对象的简单数据类型值没变,复杂数据类型值改变
const arr1 = [1, { a: 1 }]
const arr2 = arr1.concat()
arr2[0] = 2
arr2[1].a = 2
console.log(arr1[0]); //1
console.log(arr1[1].a);//2
深拷贝
//1. JSON.parse(JSON.stringify(obj))
//原理:JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,对象会开辟新的栈,实现深拷贝。
//局限性:不能拷贝方法
const arr = [1, { a: 1 }]
const arr1 = JSON.parse(JSON.stringify(arr))
arr1[1].a = 2
console.log(arr[1].a);//1
//2. 递归(推荐)
//对象、数组的深拷贝
//面试话术:
第一句:深拷贝是指新拷贝的对象不会影响就对象,要想实现深拷贝,可以用函数递归
第二句:普通拷贝的话采用赋值即可,但是遇见数组这样的我们再次调用递归即可
第三句:如果遇到对象形式,再次调用递归解决对象
第四句:一定先处理数组,在处理对象,因为万物皆对象,数组也是对象
function fn(old, newObj) {
for (let k in old) {
if (old[k] instanceof Array) {
newObj[k] = []
fn(old[k], newObj[k])
} else if (old[k] instanceof Object) {
newObj[k] = {}
fn(old[k], newObj[k])
} else {
newObj[k] = old[k]
}
}
}
const a = { a: 1, b: { c: 1 } }
const b = {}
fn(a, b)
b.b.c = 2
console.log(a); //{ a: 1, b: { c: 1 } }
//3. loadash
//在线地址 https://cdn.bootcss.com/lodash.js/4.17.11/lodash.min.js