JavaScript基础类型
- JavaScript原始类型:number、string、boolean、null、undefined、symbol(ES6)、bigint(ES10)
- JavaScript引用类型:Object(function、array、object)
1.浅克隆
定义:对象只会被克隆最外部的一层,至于更深层的对象,则依然是通过引用指向同一块内存。
//浅克隆函数
function shallowClone(o){
const obj = {}'
for(let i in o){
obj[i] = o[i];
}
return obj;
}
//被克隆对象
const oldObj = {
a:1,
b:['a','b','c'],
c:{h:{i:2}}
};
const newObj = shallowClone(oldObj);
console.log(newObj.c.h,oldObj.c.h); //{i:2} {i:2}
console.log(oldObj.c.h === newObj.c.h); //true
可以从oleObj.c.h和newObj.c.h相等可以看出,他们依然指向的是同一段内存,这就造成了如果对newObj.c.h修改的话,也会影响oleObj.c.h
newObj.c.h.i = 'change';
console.log(newObj.c.h,oldObj.c.h); //{i:'change'} {i:'change'}
2.对象深度克隆实现
定义:开辟一块新的空间,完整的复制一份,包括复杂数据类型,拷贝的这个对象和原对象无任何关系,修改什么都互不影响。
-
JSON.parse方法:JSON对象parse方法可以将JSON字符串反序列化成JS对象,stringify方法可以将JS对象序列化成JSON字符串,这两个方法结合起来就能产生一个便捷的深克隆
const newObj = JSON.parse(JSON.stringify(oldObj));
console.log(newObj.c.h === oldObj.c.h); //false
newObj.c.h.i = 'change';
console.log(newObj.c.h,oldObj.c.h); //{i:'change'} {i:2}
缺点:
- 他无法实现对函数、RegExp等特殊对象的克隆
- 会抛弃对象的constructor,所有的构造函数会指向Object
- 对象有循环引用,会报错
-
构造一个深克隆函数(递归实现)
//ES5实现方式
function deepClone(obj){
var newObj = obj instanceof Array?[]:{}
for(var item in obj){
var temple = typeof obj[item] == 'object'?deepClone(obj[item]):obj[item];
newObj[item] = temple;
}
return newObj;
}
//完整解决方案
function deepClone(obj){
if(obj === null) return null;
if(obj instanceof Date) return newDate(obj); //日期对象
if(obj instanceof RegExp) return RegExp(obj); //正则表达式
if(typeof obj === 'Function') return new function(obj){}; //函数
if(typeof obj !== 'object'){
//非复杂类型,直接返回 也是结束递归的条件
return obj
}
//[].__proto__.constructor = Array()
//{}.__proto__.constructor = Object()
//因此处理数组情况是,可以巧用这个办法来new新对象
var newObj = new obj.__proto__constructor;
for(var key in obj){
newObj[key] = deepClone(obj[key])
}
return newObj;
}
知识点补充:
-
typeof和instanceof区别?
typeof可以判断出基本数据类型(除了null的数据类型为object的bug),还可以正确判断出某个对象是否为function,其余的Date,Array等无法判断
instanceof相反,可以准确判断出复杂数据类型,但是无法判断简单数据类型