如何使用map/filter修改对象数组的内容?

15

我有以下数组:

myarray = [
    { "key": "A" },
    { "key": "B" }
]
如何在JavaScript中使用map/filter函数来执行以下操作的等效操作:
for (var i = 0; i < myarray.length; i++) {
    if ( myarray[i].key == 'B') {
        myarray[i].mark = "marked!"
    }
}

在我的尝试中,输出中没有mark属性:

myarray.filter((someobject) => someobject.key == 'B').mark = "marked!"
console.log(myarray) // this does not show the "mark" key.

注意:我希望修改原始数组。


1
mapfilter都不会 修改 数组,它们只会创建新的数组。 - Bergi
1
你的代码有什么问题吗?我认为那是“最好的方法”,因为意图很明显。 - Heretic Monkey
2个回答

35

如果只有一个匹配项,您可以使用 find

myarray.find(someobject => someobject.key == 'B').mark = "marked!"

如果您不知道匹配数,则使用for循环似乎是最好的方法。否则,您可以选择使用filterforEach

myarray.filter(someobject => someobject.key == 'B')
       .forEach(someobject => someobject.mark = "marked!")

1
我觉得这个查找非常优雅。 - Rolando
目前这个对我有用:myarray.find(someobject => someobject.key == 'B')[0].mark = "marked!" - AlpSenel
不可变性怎么样? - Thanos M
1
@ThanosM,问题是“如何...修改”,并且问题以“我想修改原始数组”结束。因此,明确要求进行变异。 - trincot

5
什么是在JavaScript中使用map/filter函数等效于此代码的最佳方法?
并非全部,因为map和filter都不会修改一个数组,它们只会创建新的数组。您可以使用类似以下的东西:
let newArray = myArray.map(({key} => ({key, marked: key=='B'}));

但是最适合您的代码的ES6等效代码是:
for (let v of myArray) if (v.key == 'B') v.mark = 'marked';

您也可以使用forEach,但我强烈建议不要在函数式方法中掩盖副作用:

myArray.filter(({key}) => key == 'B').forEach(v => { v.mark = 'marked'; });

我不明白为什么使用for循环比foreach更好。您能解释一下吗? - Marco Luzzara
@Marco Luzzara:使用for循环并不比使用可链接方法更好。在这种情况下,.filter.forEach按顺序完全有意义,并且这也是JS首次具有可链接方法的原因。所有内容看起来都很干净合理。尽管如此,我会减少.filter示例的复杂性,因为没有必要进一步解构.filter内部的item以获取key属性。.filter(item => item.key === 'B')看起来更易读和可维护。 - Denialos
1
@MarcoLuzzara 这种方式更短,性能更高,看起来更命令式,并且允许使用任意控制结构。 - Bergi
感谢您的解释。 - Marco Luzzara

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接