写作背景
项目中基本有写好的第三方库供我们调用,那么为什么我这里还要书写这个呢 1: 这种东西可以提升我们书写代码的能力,以及思考问题和解决问题的思想
正式编写
何为深度clone ?
就是在原来对象的基础上复制一模一样的东西,clone 之后,原对象的变化不会应用到clone对象中
先来实现一个浅clone
function deepClone(source){
let target ={};
for (const key in source) {
if (Object.hasOwnProperty.call(source, key)) {
target[key] = source[key]
}
}
return target
}
相信这个大家基本写的出来。接下来我们开始分析
1:没有对传进来的source进行分析,可能为null,可能是数组
解决方案
function deepClone(source){
// 判断为null
if(source===null){
return null
}
// 判断数组还是对象
let target =Array.isArray(source)?[]:{};
for (const key in source) {
if (Object.hasOwnProperty.call(source, key)) {
target[key] = source[key]
}
}
return target
}
2: 这里还会存在一个问题就是如果对象的属性是Symbol 那么使用forin 是无法遍历出Symbol类型的,这里的解决方案是既然是es6新增属性,那么可以利用es6的ReflectApi 进行解决
function deepClone(source){
// 判断为null
if(source===null){
return null
}
// 判断数组还是对象
let target =Array.isArray(source)?[]:{};
// 利用ReflectApi 可以遍历出Symbol属性
Reflect.ownKeys(source).forEach(key=>{
target[key] = source[key]
})
return target
}
3 如何解决深度clone?既需要判断原对象该属性是引用还是原始值(函数是应用值但是copy 可以直接赋值)
解决方案
function deepClone(source){
// 判断为null
if(source===null){
return null
}
// 判断数组还是对象
let target =Array.isArray(source)?[]:{};
// 利用ReflectApi 可以遍历出Symbol属性
Reflect.ownKeys(source).forEach(key=>{
const src = source[key];
//这里不用判断null特殊情况因为之前的判断过
if(typeof src === "object"){
target[key] = deepClone(src)
}else{
target[key] = src
}
})
return target
}
4:以上基本实现了深度clone的方法,但是在某些特殊情况还是会存在问题,比如
在引用循环的时候
const obj = {
name:"hello",
jk:{
name:"jk"
}
}
obj.lk ={
a:"a",
b: obj.jk
}
于是想到用缓存 这里使用数组实现(weakMap 也行)
function deepClone(source,cacheArr=[]){
// 判断为null
if(source===null){
return null
}
const findItem = cacheArr.find(item=>item.source ===source)
if(findItem){
return findItem.target
}
// 判断数组还是对象
let target =Array.isArray(source)?[]:{};
// 利用ReflectApi 可以遍历出Symbol属性
Reflect.ownKeys(source).forEach(key=>{
const src = source[key];
//这里不用判断null特殊情况因为之前的判断过
if(typeof src === "object"){
target[key] = deepClone(src,cacheArr)
}else{
target[key] = src
}
cacheArr.push({
source:src,
target:target[key]
})
})
return target
}
5:以上基本实现了深度clone的方法,这样是不是就是最终版了呢?答案依然是不是的,因为在数据足够多的情况下会存在爆栈?怎么解决。我不想解决,因为使用树形遍历又会带来下一个问题,无穷无尽,目前我只能学习到这里,也许后面会补充这个。