数据类型
在讨论深拷贝与浅拷贝之前,我们先来聊一聊数据类型,因为他和深浅拷贝有关。
在js中,数据类型分为基本数据类型(NUmber、String、Boolean、Null、Undefined、Symbol)和引用数据类型(Object、Array、Function)。
我们知道,基本数据类型是直接存储在栈中,而引用数据类型是存在堆内存中的,栈中存的,是指向堆内存地址的指针。
深拷贝、浅拷贝
深浅拷贝是针对引用数据类型。
简单来说,浅拷贝是只拷贝了引用数据类型的在栈中的指针,它们指向的都是同一个堆内存地址,所以浅拷贝在某些情况会造成改变数据后导致别的另一份数据也同步被改变的情况;而深拷贝是直接将堆内存中存储的数据直接复制一份,不会有浅拷贝互相影响的问题。
浅拷贝的方法
- Object.assign()
- Array.prototype.concat()
- Array.prototype.slice()
slice() 方法可从已有的数组中返回选定的元素。
语法:arrayObject.slice(start,end)。
深拷贝的方法
- JSON.parse(JSON.stringify())
将一个对象先转为json字符串,然后再转回来,这样可以实现深拷贝。
但是这个方法有个缺陷,可以实现对象或数组的深拷贝,但是不能处理函数,函数经过这样处理后会变成null。
手写深拷贝
function deepClone(source) {
//引用类型=>数组[],对象{}
const targetObj = source.constructor === Array ? [] : {}
for (let keys in source) {
// 检测一个对象是否含有指定名称的属性,并返回一个布尔值,指示属性是否为对象的自有属性(而不是继承而来的)
if (source.hasOwnProperty(keys)) {
//数组和对象
if (source[keys] && typeof source[keys] === "object") {
//targetObj[keys] = source[keys].constructor === Array ? [] : {}
targetObj[keys] = deepClone(source[keys])
} else {
//基本类型
targetObj[keys] = source[keys]
}
}
}
return targetObj
}