在写深拷贝之前,有必要说一下js的数据类型
一.js数据类型
1.1 分类
js数据类型分为两类:原始数据类型、引用数据类型
原始数据类型:string,number,boolean,null,undefined,symbol
引用数据类型:function,array,object等
1.2 区别
原始数据类型存储在栈内存中,引用数据类型存储在堆内存中。
原始数据类型存储的数据是值,引用数据类型存储的数据是空间地址。
1.3 赋值
原始数据类型赋值时是直接赋值数值。修改原数据不会影响新变量。
引用数据类型赋值时是赋值空间地址。修改原数据有可能会影响新变量
let str = "banana"
let str2 = str
str2 = "apple"
// str == "banana" str2 == "apple"
let obj = { name : "banana" }
let obj2 = obj
obj2.name = "apple"
// obj.name == "apple"
二.数据深拷贝
引用数据类型赋值时赋值的是空间地址,修改原数据会影响新变量,这时候就需要用到深拷贝。
2.1 JSON(不考虑引用类型)
使用json的方法实现深拷贝
JSON.parse(JSON.stringify(obj))
2.2 递归(不考虑引用类型)
function deepClone(obj){
// 判断是引用类型还是原始类型
if(typeof obj === "object" && obj !== null){
// 判断是数组还是对象类型
let newObj = Array.isArray(obj)?[]:{}
for(let key in obj){
newObj[key] = deepClone(obj[key])
}
return newObj
}else{
return obj
}
}
2.3 考虑引用类型
function foo3(target,map = new Map()){
if(target === null || typeof target !=='object')return target;
let constructor = target.constructor;
if(/^(Function|Date|Map|Set|RegExp)$/i.test(constructor.name)){
return new constructor(target)
}
if(map.get(target))return map.get(target);
map.set(target,true);
let res = Array.isArray(target) ? [] : {}
for(let key in target){
res[key] = foo3(target[key],map)
}
return res
}
网友评论