深拷贝和浅拷贝
1、工作中频率最高的深浅拷贝
//object.assign
Object.assign({}, obj):obj为单层对象能实现"深拷贝";obj为深层对象,则只能视为浅拷贝
//JSON.parse(JSON.stringify(xxx))
只能实现普通对象(function,Symbol(),undefined这三种除外)的深拷贝,当对function,Symbol(),undefined这三种进行拷贝时,会造成数据丢失
2、object.assign()
let obj = {a:1,b:2}
let newObj = {...obj}
newObj.a = 5
console.log(obj.a) //1
let obj1 = {a:{c:5},b:2}
let newObj1 = {...obj1}
newObj1.a.c = 10
console.log(obj1.a.c) //10
3、JSON.parse(JSON.stringify(xxx))
let test = {
a:{
c:5
},
arr:[1,2],
fuc:function(){
console.log("fuc");
},
u:undefined,
b:8,
s:Symbol(),
n:null,
t:true
}
let copy = JSON.parse(JSON.stringify(test))
console.log("copy", copy);
test.a.c = 7
console.log(copy.a.c); //5
test.t = false
console.log(copy.t);//true
test.b = 10
console.log(copy.b); //8
JSON.parse(JSON.stringify(XXX))能实现大部分数据类型的深拷贝,但是当拷贝数据类型为Symbol、undefined和function时,则会造成数据的丢失。
- 注意:当数据类型为BigInt时,会报错显示JSON.stringify无法序列化BigInt。
- 如果想进一步理解,需要去对JSON.parse()和JSON.stringify()更深一步的了解
4、简单的深拷贝
//只针对对象和数组
function deepClone(obj) {
let cloneObj = obj instanceof Array ? [] : {}
for(let item in obj) {
cloneObj[item] = typeof obj[item] === "object" ? deepClone(obj[item]) : obj[item]
}
return cloneObj
}
5、数据类型的检测
-
typeof一般用于检测基本数据类型,检测引用数据类型都返回Object
- //注意:typeof检测null也会返回object,用typeof检测function返回的function
-
instanceof主要是用来检测引用数据类型,不能用来检测基本数据类型。A instanceof B,如果A是B的实例对象,则返回true,否则返回false。即如果能在A的原型链上找到B的原型,则为true
- //注意:[] instanceof Object 也为true,这是因为[].proto ->Array.prototype,Array.prototype._proto_指向Object.prototype。类似的,Date、RegExp和函数也会形成这样的一条原型链。
-
constructor根据数据类型的构造函数返回类型,null和undefined没有构造函数,因此不能判断
-
Object.prototype.toString.call()可以准确的检测所有数据类型
6、复杂的深拷贝
//考虑RegExp、Date
function deepClone(target, map = new Map()) {
if(target instanceof RegExp) return new RegExp(target)
if(target instanceof Date) return new Date(target)
if(typeof target === "object" && targrt !== "null" && target !== "undefined") {
let cache = map.get(target)
if(cache) return
let result = new target.constructor
map.set(target,result)
if(Array.isArray(target)){
target.forEach((item, key) => {
result[key] = deepClone(item, map)
})
}else {
Object.keys(target).forEach(key => {
result[key] = deepClone(target[key], map)
})
}
return result
}else {
return target
}
}