真正的项目中学习知识点
知识点一 对象的克隆Object.clone/为什么不用JSON.parse(JSON.stringfy())
这个知识点一开始作为前端的我,有点迷惑,在js里好像并没有这个函数,查阅代码文档,发现项目里的这个函数是自己写的函数放在Object原型对象上。然后还发现这个函数是在Java中存在的。
其实这个说白点就是实现对象的深拷贝,而深拷贝通俗讲将一个对象的值赋值给另一个对象,但是这两个对象互不影响,指向的是两个不同的地址。想到这个我就跟我老大说既然是对象的深拷贝,为什么不直接用 JSON.parse(JSON.stringfy()),因为本人在写代码的时候,比如请求数据赋值给一个新的对象,然后改变这个新对象的值就是通过JSON.parse(JSON.stringfy())实现的。
缺点:
1. 无法处理特殊对象:`JSON.stringify()`会忽略一些特殊对象的属性,比如函数、正则表达式、
日期对象等。拷贝后的对象将丢失这些属性。
2. 无法处理循环引用:如果对象存在循环引用(即对象内部的某个属性引用了对象本身),
`JSON.stringify()`会抛出错误,导致拷贝失败。
3. 无法拷贝原型链上的属性和方法:拷贝后的对象将失去原型链上的属性和方法。
其实最常见的缺点就是JSON.parse(JSON.stringify())
只能处理JSON支持的数据类型,而undefined
不是JSON的有效值,因此会被忽略。
看一个代码例子
const originalObject = {
prop1: 'value1',
prop2: undefined,
prop3: null
};
// 利用JSON.parse(JSON.stringify()) 实现深拷贝
const clonedObject = JSON.parse(JSON.stringify(originalObject));
console.log(clonedObject);
结果为
{
prop1: 'value1',
prop3: null
}
我们可以看到当一个对象里的某个属性值为undefined时,它拷贝过来后并没有prop2这个属性。
我的天啊!万一这个prop2虽然是undefined但是有意义,咋办啊!
所以 在真实项目开发中,最好少用JSON.parse(JSON.stringify())
所以我们可以自己写一个深拷贝的函数,然后引入使用,或者我们也可以从一些库函数里引入它们封装好的函数,比如lodash里的cloneDeep函数
lodash
const _ = require('lodash');
const originalObject = { ... }; // 要克隆的原始对象
const clonedObject = _.cloneDeep(originalObject);
手写
function deepClone(obj){
if (obj === null || typeof obj !== 'object') {
return obj;
}
let clone = Array.isArray(obj) ? []:{};
for(let key in obj){
// 对象上有这个key 而不是原型链上有,因为js查找某些属性时是逐步查找
// 自身 -> 原型对象 ->原型对象的原型对象 -> Object.prototype ->null
if(obj.hasOwnProperty(key)){
clone[key] = deepClone(obj[key])
}
}
return clone;
}
我这里把obj.hasOwnProperty(key)这个剖析再利用代码讲一下。
当使用obj.hasOwnProperty(key)
时,它会检查一个对象obj
是否具有指定的属性key
。
这个方法会返回一个布尔值,如果对象具有该属性,则返回true
;否则,返回false
const obj = {
prop1: 'value1'
};
const prototypeObj = {
prop2: 'value2'
};
Object.setPrototypeOf(obj, prototypeObj);
console.log(obj.prop1); // 'value1',自身属性
console.log(obj.prop2); // 'value2',原型对象的属性
console.log(obj.toString); // [Function: toString],原型对象的原型对象的属性
console.log(obj.hasOwnProperty('prop1')); // true,自身属性
console.log(obj.hasOwnProperty('prop2')); // false,原型对象的属性
在这个例子中,`obj`对象具有自身属性`prop1`,因此直接访问并返回其值。
`obj`对象的原型对象`prototypeObj`具有属性`prop2`,因此也可以直接访问并返回其值。
`obj`对象的原型对象的原型对象是`Object.prototype`,它具有一些通用的属性和方法,如`toString`。
最后,`obj`对象自身没有`hasOwnProperty`方法,但它可以通过原型链找到`Object.prototype`上的该方法。
总结
本来想把遇到的所有的问题,都记录下来当初笔记,但是这一个就篇幅过长,因为本人不喜一眼全是文字,所以后面的问题放到下一篇中。懒了,今天去参加了开发者大会,明天在总结。
© 版权声明
文章版权归作者所有,未经允许请勿转载,侵权请联系 admin@trc20.tw 删除。
THE END