为什么不在 forEach 工作中重新分配参数元素
why doesn't reassigning the parameter element in forEach work
这里就不多解释了,我就直奔主题吧。
对于以下代码块:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach((item, i) => {
item = {
...item,
...changes
}
})
console.log(items) // items NOT reassigned with changes
items.forEach((item, i) => {
items[i] = {
...item,
...changes
}
});
console.log(items) // items reassigned with changes
为什么在元素迭代时重新分配值不会更改数组中的对象?
item = {
...item,
...changes
}
但是通过使用索引访问它来更改它会更改数组中的对象吗?
items2[i] = {
...item,
...changes
}
更新数组中对象的最佳方法是什么? items2[i]
理想吗?
正如 forEach 的 MDN 页面所说:
forEach() executes the callbackFn function once for each array
element; unlike map() or reduce() it always returns the value
undefined and is not chainable. The typical use case is to execute
side effects at the end of a chain.
看这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
这意味着虽然您确实为项目创建了新对象,但它并未作为该数组索引的值返回。与您的第二个示例不同,第一个示例不会更改原始数组,而只是创建新对象和 returns undefined。这就是为什么你的数组没有被修改。
为此我会选择经典 Object.assign
:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach( (item) => Object.assign(item,changes) )
console.log(items)
Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
对参数重新分配说不!
这是对 JavaScript 等高级语言的一种基本理解。
Function parameters are temporary containers of a given value.
因此任何“重新分配”都不会改变原始值。
例如看下面的例子。
let importantObject = {
hello: "world"
}
// We are just reassigning the function parameter
function tryUpdateObjectByParamReassign(parameter) {
parameter = {
...parameter,
updated: "object"
}
}
tryUpdateObjectByParamReassign(importantObject)
console.log("When tryUpdateObjectByParamReassign the object is not updated");
console.log(importantObject);
正如您所见,当您重新分配参数时,原始值将不会被触及。甚至还有一个不错的 Lint rule,因为这是一个极易出错的区域。
突变在这里起作用,但是....
但是,如果您“改变”变量,这将起作用。
let importantObject = {
hello: "world"
}
// When we mutate the returned object since we are mutating the object the updates will be shown
function tryUpdateObjectByObjectMutation(parameter) {
parameter["updated"] = "object"
}
tryUpdateObjectByObjectMutation(importantObject)
console.log("When tryUpdateObjectByObjectMutation the object is updated");
console.log(importantObject);
所以回到你的代码片段。在 foreach 循环中发生的是每个数组项的“函数调用”,其中数组项作为参数传入。与上面类似,这里的工作是突变。
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach((item, i) => {
// Object assign just copies an object into another object
Object.assign(item, changes);
})
console.log(items)
但是,最好避免突变!
this can lead to even more bugs以后最好不要变异。更好的方法是使用地图并获得全新的对象集合。
const items = [{
id: 1,
name: 'one'
},
{
id: 2,
name: 'two'
},
];
const changes = {
name: 'hello'
}
const updatedItems = items.map((item, i) => {
return {
...item,
...changes
}
})
console.log({
items
})
console.log({
updatedItems
})
您可以采取的另一种方法是使用 map
并根据原始数据和更改创建一个新数组:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
const newItems = items.map((item) => {
...item,
...changes
})
console.log(newItems);
但是如果你需要修改原始数组,它要么通过索引访问元素,要么Object.assign
。尝试使用 =
运算符直接分配值是行不通的,因为 item
参数被传递给回调 by value 而不是 by reference - 你没有更新数组指向的对象。
这里就不多解释了,我就直奔主题吧。
对于以下代码块:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach((item, i) => {
item = {
...item,
...changes
}
})
console.log(items) // items NOT reassigned with changes
items.forEach((item, i) => {
items[i] = {
...item,
...changes
}
});
console.log(items) // items reassigned with changes
为什么在元素迭代时重新分配值不会更改数组中的对象?
item = {
...item,
...changes
}
但是通过使用索引访问它来更改它会更改数组中的对象吗?
items2[i] = {
...item,
...changes
}
更新数组中对象的最佳方法是什么? items2[i]
理想吗?
正如 forEach 的 MDN 页面所说:
forEach() executes the callbackFn function once for each array element; unlike map() or reduce() it always returns the value undefined and is not chainable. The typical use case is to execute side effects at the end of a chain.
看这里:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
这意味着虽然您确实为项目创建了新对象,但它并未作为该数组索引的值返回。与您的第二个示例不同,第一个示例不会更改原始数组,而只是创建新对象和 returns undefined。这就是为什么你的数组没有被修改。
为此我会选择经典 Object.assign
:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach( (item) => Object.assign(item,changes) )
console.log(items)
Properties in the target object are overwritten by properties in the sources if they have the same key. Later sources' properties overwrite earlier ones. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
对参数重新分配说不!
这是对 JavaScript 等高级语言的一种基本理解。
Function parameters are temporary containers of a given value.
因此任何“重新分配”都不会改变原始值。
例如看下面的例子。
let importantObject = {
hello: "world"
}
// We are just reassigning the function parameter
function tryUpdateObjectByParamReassign(parameter) {
parameter = {
...parameter,
updated: "object"
}
}
tryUpdateObjectByParamReassign(importantObject)
console.log("When tryUpdateObjectByParamReassign the object is not updated");
console.log(importantObject);
正如您所见,当您重新分配参数时,原始值将不会被触及。甚至还有一个不错的 Lint rule,因为这是一个极易出错的区域。
突变在这里起作用,但是....
但是,如果您“改变”变量,这将起作用。
let importantObject = {
hello: "world"
}
// When we mutate the returned object since we are mutating the object the updates will be shown
function tryUpdateObjectByObjectMutation(parameter) {
parameter["updated"] = "object"
}
tryUpdateObjectByObjectMutation(importantObject)
console.log("When tryUpdateObjectByObjectMutation the object is updated");
console.log(importantObject);
所以回到你的代码片段。在 foreach 循环中发生的是每个数组项的“函数调用”,其中数组项作为参数传入。与上面类似,这里的工作是突变。
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
items.forEach((item, i) => {
// Object assign just copies an object into another object
Object.assign(item, changes);
})
console.log(items)
但是,最好避免突变!
this can lead to even more bugs以后最好不要变异。更好的方法是使用地图并获得全新的对象集合。
const items = [{
id: 1,
name: 'one'
},
{
id: 2,
name: 'two'
},
];
const changes = {
name: 'hello'
}
const updatedItems = items.map((item, i) => {
return {
...item,
...changes
}
})
console.log({
items
})
console.log({
updatedItems
})
您可以采取的另一种方法是使用 map
并根据原始数据和更改创建一个新数组:
const items = [
{ id: 1, name: 'one' },
{ id: 2, name: 'two' },
];
const changes = {
name: 'hello'
}
const newItems = items.map((item) => {
...item,
...changes
})
console.log(newItems);
但是如果你需要修改原始数组,它要么通过索引访问元素,要么Object.assign
。尝试使用 =
运算符直接分配值是行不通的,因为 item
参数被传递给回调 by value 而不是 by reference - 你没有更新数组指向的对象。