【问题标题】:Understanding Behaviour of Find method in Javascript了解 Javascript 中 Find 方法的行为
【发布时间】:2021-12-05 08:06:53
【问题描述】:
let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
let exists = arr.find(x => x.age < 4);
exists.age += 1;
console.log(arr);

//output is [{age:4},{age:5},{age:6},{age:7}];

在上面的示例中,我正在更新 find 方法返回的结果,但它也更改了原始数组的值,为什么会这样?

【问题讨论】:

  • 删除exists.age += 1;
  • 因为你的修改对象...exists.age += 1;

标签: javascript arrays higher-order-functions


【解决方案1】:

因为 JavaScript 中的对象是通过引用传递的,所以你得到了那个对象({age: 3}),然后在它的“age”键上加了 1,所以原来的对象也改变了。

let obj1 = {age: 3 , name: 'jack' }
let obj2 = obj1

console.log(obj1 === obj2 )  // true

// if you change the second object , the first one will change too :

obj2.age = 15

console.log(obj1 , obj2 )  

// obj1 = { age: 15 , name: 'jack' } 
// obj2 = { age: 15 , name: 'jack' }

【讨论】:

    【解决方案2】:

    Array.prototype.find 将返回满足您作为回调函数传递的条件的第一个元素。

    因为您正在寻找一个其age 属性小于4 的对象。所以它将返回第一个对象(其age3)。因此,如果您要检查 existsarr[0] 的相等性,那么它将返回满足条件的对象

    let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
    let exists = arr.find((x) => x.age < 4);
    
    console.log(exists === arr[0])

    因此,如果您要对 find 方法返回的对象进行任何类型的更改,那么原始对象将反映更改。

    因为两者都是同一个对象,只是引用不同。


    如果您不想改变原始对象,那么您应该在对该对象进行任何类型的更改之前克隆它。

    Note: Both of the following method does shallow copy

    1) 使用spread syntax

    let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
    let exists = arr.find((x) => x.age < 4);
    
    const clone = { ...exists };
    clone.age += 1;
    console.log(arr);
    /* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    2) 使用Object.assign

    let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
    let exists = arr.find((x) => x.age < 4);
    
    const clone = Object.assign({}, exists);
    clone.age += 1;
    console.log(arr);

    【讨论】:

      【解决方案3】:

      因为你有一个对象引用数组。在 JavaScript 中,对象实际上存储在其他地方(称为“堆”),而对象变量实际上只包含对对象的 references。所以原因是因为您正在更新同一个对象。

      如果你想做一个对象的浅克隆,你可以使用Object.assign({}, obj)

      此外,与您的问题没有直接关系,如果您的对象属性 它们自己 包含其他对象引用,包括数组,并且您希望这些也是副本,那么您必须深入-克隆它们。这不是由普通的 JavaScript 函数或方法自动完成的。您必须找到为您执行此操作的代码或自己编写。上次我这样做时,我使用了 randa 的克隆功能,因为我团队中的另一个开发人员已经将 ramda 库导入到我们的项目中。对您的项目最有意义的可能会有所不同。

      【讨论】:

        猜你喜欢
        • 2020-12-18
        • 1970-01-01
        • 2022-10-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-07
        • 2023-04-04
        • 1970-01-01
        • 2014-12-17
        相关资源
        最近更新 更多