了解 Javascript 中 Find 方法的行为
Understanding Behaviour of Find method in Javascript
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 方法返回的结果,但它也改变了原始数组的值,为什么这样呢?
Array.prototype.find
将 return 满足您作为回调函数传递的条件的第一个元素。
因为您正在寻找 age
属性 小于 4
的对象。所以它将 return 第一个对象(其 age
是 3
)。因此,如果您要检查 exists
和 arr[0]
是否相等,那么它将 return 对象满足条件
let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
let exists = arr.find((x) => x.age < 4);
console.log(exists === arr[0])
因此,如果您打算对通过 find
方法 return 编辑的对象进行任何类型的修改,那么原始对象将反映这些更改。
因为两者都是同一个对象,只是引用不同而已。
如果您不想改变原始对象,那么您应该在对该对象进行任何类型的更改之前克隆它。
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);
因为你有一个对象引用数组。在 JavaScript 中,对象实际上存储在别处(称为“堆”),对象变量实际上仅包含对象的 引用 。所以原因是因为你正在更新同一个对象。
如果你想做一个对象的浅克隆,你可以使用Object.assign({}, obj)
。
此外,与您的问题没有直接关系,如果您的对象属性 本身 包含其他对象引用,包括数组,并且您希望它们也成为副本,您将不得不深度克隆它们。这不是由股票 JavaScript 函数或方法自动完成的。您必须找到为您执行此操作的代码或自己编写。上次我这样做时,我使用了 randa 的克隆功能,因为我团队中的另一个开发人员已经将 ramda 库导入到我们的项目中。对您的项目最有意义的可能有所不同。
这是因为 JavaScript 中的对象是通过引用传递的,您在存在的对象 ({age : 3} ) 中添加了 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' }
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 方法返回的结果,但它也改变了原始数组的值,为什么这样呢?
Array.prototype.find
将 return 满足您作为回调函数传递的条件的第一个元素。
因为您正在寻找 age
属性 小于 4
的对象。所以它将 return 第一个对象(其 age
是 3
)。因此,如果您要检查 exists
和 arr[0]
是否相等,那么它将 return 对象满足条件
let arr = [{ age: 3 }, { age: 5 }, { age: 6 }, { age: 7 }];
let exists = arr.find((x) => x.age < 4);
console.log(exists === arr[0])
因此,如果您打算对通过 find
方法 return 编辑的对象进行任何类型的修改,那么原始对象将反映这些更改。
因为两者都是同一个对象,只是引用不同而已。
如果您不想改变原始对象,那么您应该在对该对象进行任何类型的更改之前克隆它。
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);
因为你有一个对象引用数组。在 JavaScript 中,对象实际上存储在别处(称为“堆”),对象变量实际上仅包含对象的 引用 。所以原因是因为你正在更新同一个对象。
如果你想做一个对象的浅克隆,你可以使用Object.assign({}, obj)
。
此外,与您的问题没有直接关系,如果您的对象属性 本身 包含其他对象引用,包括数组,并且您希望它们也成为副本,您将不得不深度克隆它们。这不是由股票 JavaScript 函数或方法自动完成的。您必须找到为您执行此操作的代码或自己编写。上次我这样做时,我使用了 randa 的克隆功能,因为我团队中的另一个开发人员已经将 ramda 库导入到我们的项目中。对您的项目最有意义的可能有所不同。
这是因为 JavaScript 中的对象是通过引用传递的,您在存在的对象 ({age : 3} ) 中添加了 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' }