真实实习,项目中学习到的知识点一

真正的项目中学习知识点

知识点一 对象的克隆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`上的该方法。

总结

本来想把遇到的所有的问题,都记录下来当初笔记,但是这一个就篇幅过长,因为本人不喜一眼全是文字,所以后面的问题放到下一篇中。懒了,今天去参加了开发者大会,明天在总结。

猜你喜欢

转载自juejin.im/post/7250687457800175673
今日推荐