手写实现一个深拷贝
部分一:
简介:手写实现一个深拷贝属于数据结构的知识点,数据类型包含基本类型和引用类型,基本类型存储在栈中;引用数据类型存储在堆中;基本数据类型没有浅拷贝和深拷贝的区分,浅拷贝和深拷贝的问题存在于引用数据类型中。
浅拷贝:只拷贝了内存空间的地址;
深拷贝:开辟新的内存空间,两块空间相互之间不影响;
解构赋值是不是深拷贝?
不是,一维数组或对象是深拷贝,多维则是浅拷贝;
深拷贝方法:
JSON.parse(JSON.stringfy(obj))
手写深拷贝方法:
/*手写深拷贝思路:
1.判断拷贝的对象是数组还是对象
2.遍历属性
是否还有数组或对象 =>递归
基本数据类型 => 赋值*/
const deepCopy = (obj) =>{
//1.判断拷贝的对象是数组还是对象
const newObj = obj.constructor === Array ? [] : {}
//2.遍历属性
for(let key in obj){
if(obj.hasOwnProperty(key)){
//是否还有数组或对象
if(obj[key] && typeof obj[key] === 'object'){
//递归
newObj[key] = deepCopy(obj[key])
}else{
//基本数据类型
newObj[key] = obj[key];
}
}
}
return newObj;
}
const object1 = {
a:1,
b:'深拷贝',
arr:[1,2,3],
boj2:{
aa:1,
bb:'深拷贝'
}
}
const x = deepCopy(object1);
x.c = 100;
console.log(x)
console.log(object1)
//hasOwnProperty 会返回一个布尔值,判断对象中是否存在该属性
部分二:
上面的obj.hasOwnProperty(key)存在一些问题,由于javascript没有将hasOwnProperty作为一个敏感词,外部可以自己定义它,就有可能覆盖该属性,从而失去它原本的功能,列如:
function test(){
const ob = {a:1}
ob.hasOwnProperty = 0;
console.log(ob.hasOwnProperty('a'))
}
test()
function test(){
const ob = {a:1}
ob.hasOwnProperty = () => false;
console.log(ob.hasOwnProperty('a'))
}
test()
解决方法:
使用Object.prototype.hasOwnProperty.call(obj, key)
改进深拷贝
/*手写深拷贝思路:
1.判断拷贝的对象是数组还是对象
2.遍历属性
是否还有数组或对象 =>递归
基本数据类型 => 赋值*/
const deepCopy = (obj) =>{
//1.判断拷贝的对象是数组还是对象
const newObj = obj.constructor === Array ? [] : {}
//2.遍历属性
for(let key in obj){
if(Object.prototype.hasOwnProperty.call(obj, key)){
//是否还有数组或对象
if(obj[key] && typeof obj[key] === 'object'){
//递归
newObj[key] = deepCopy(obj[key])
}else{
//基本数据类型
newObj[key] = obj[key];
}
}
}
return newObj;
}
const object1 = {
a:1,
b:'深拷贝',
arr:[1,2,3],
boj2:{
aa:1,
bb:'深拷贝'
}
}
const x = deepCopy(object1);
x.c = 100;
console.log(x)
console.log(object1)
//hasOwnProperty 会返回一个布尔值,判断对象中是否存在该属性
//Object.prototype.hasOwnProperty.call(obj, key)
// 不要轻易使用Object.prototype的方法:
// 例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf 方法:
// 这些方法可能被对象自身的同名属性覆盖或者对象是个null对象。
// 如果一定要使用,可以使用Object.prototype.hasOwnProperty.call()、Object.keys().includes()、in等其余方式进行替换,最大程度的保证程序不出bug!!!
总结:
不要轻易使用Object.prototype的方法,例如 hasOwnProperty, propertyIsEnumerable 和 isPrototypeOf 方法,这些方法可能被对象自身的同名属性覆盖或者对象是个null对象。
如果一定要使用,可以使用Object.prototype.hasOwnProperty.call()、Object.keys().includes()、in等其余方式进行替换。