一、对象深拷贝简单的方法:JSON序列化
- 方法
通过将对象转换成JSON格式并转换回对象,实现深拷贝
let a1 = {
a:"hello",
b:"world",
c:[1,2,3],
d:{
a:1,
b:2
}
}
let a2 = JSON.parse(JSON.stringify(a1))
console.log(a2);
- JSON序列化拷贝的缺点
a.不支持函数function
b.不支持undefined
c.不支持symbol
d.不支持Date(序列化之后会转换成ISO8601字符串)
(以上缺点究其原因其实就是因为JSON不支持这些格式)
5.不支持环状引用 (环状引用就是a.self = a,类似自己引用自己或者引用成环形的结构)
二、实现手写深拷贝函数
class DeepCloner{
constructor(){
this.cache = []
}
clone(source){
//2.对于引用类型(引用类型要么是对象,要么是对象的子类型)我们需要进行判断类型,然后对结果进行响应不同的初始化
if (source instanceof Object) {
//3.只要是引用类型,在正式拷贝前我们需要判断这个数据是否曾经出现过
//如果出现过,说明这是个环引用,那么我们直接返回
//如果没出现,我们则继续
let cacheDist = this.cacheFind(source)
if (cacheDist) {
return cacheDist
}else{
//4.进入到这里说明这个引用类型的数据曾经没有拷贝过
//我们需要进行一个个的子类型判断,然后进行不同的初始化
//是数组我们就初始化为数组,是对象我们就初始化为对象
let dist
if (source instanceof Array) {
dist = []
}else if (source instanceof Function) {
//5.对于函数类型,我们初始化为一个函数,这个函数调用这个传入进来的函数
dist = function() {
return source.call(this,...arguments)
}
}else if (source instanceof RegExp) {
dist = new RegExp(source.source,source.flags)
}else if (source instanceof Date) {
dist = new Date(source)
} else{
dist = {}
}
//6.初始化完毕后,在正式深拷贝前,我们需要进行一个缓存,同时把原数据和新数据进行存储
//方便我们后续进行判断
this.cache.push([source,dist])
//7.开始时进行深拷贝
for (const key in source) {
//8.通常我们是会深拷贝数据的原型,因为原型是一个很大的坑,
//比如原型上有一个函数,那么这个函数的原型又是继承自某个原型
//将所有原型拷贝将会是一个非常大的工作量,所以不拷贝原型
//这里判断该类型是否为自身的属性,如果是,则拷贝,不是则跳过
if (source.hasOwnProperty(key)) {
dist[key] = this.clone(source[key])
}
}
//9.拷贝完成后,返回
return dist
}
}
//1.深拷贝思路,对于普通类型,我们直接返回即可
return source
}
cacheFind(source){
for (let index = 0; index < this.cache.length; index++) {
if (this.cache[index][0] === source) {
return this.cache[index][1]
}
}
return undefined
}
}
module.exports = DeepCloner
标签:return,笔记,source,JSON,引用,dist,手写,拷贝
From: https://www.cnblogs.com/icerain-black/p/18051675