Javascript:以有状态的方式有效地用指定值替换数组中具有 属性 的对象?

Javascript: Efficiently replace Object in Array that has property with specified value in a stateful manner?

可能这个问题已经被问过并回答过一千次了,但我找不到。抱歉:(

对于这个概念,我在 javascript 中有以下数组(我在这里描述了最坏的情况):

var array1 = [{id: 8, text: "lala"},/* a lot of elements in between,*/ {id: 79, text: "lolo"}]

现在我想用对象 {randomProperty1: "lulu"} 替换当前具有 id: 79 的元素。我不想在之后替换数组,因为我在像 vuejs 这样的反应式系统中将它用作反应式 属性,所以它应该保持有状态。所以我不能做类似的事情:

array1 = array1.map(obj=>obj.id===79?{randomProperty1: "lulu"}:obj);

到目前为止,我天真的方法是做这样的事情:

const elem = array1.find(obj=>obj.id===79);
const index = array1.indexOf(elem);
array1[index] = {randomProperty1: "lulu"}

但据我所知,现在我必须遍历我的数组两次。考虑到每次我的鼠标移动时我都有一个巨大的阵列执行此操作,并且可能还必须重新计算我的新对象,如果我只通过我的阵列一次感觉更好。在所有其他情况下,这显然是并且可能仍然是过早的优化,但我对此很感兴趣。

我梦想的方法是这样的(伪代码):

const elem = array1.find(o=>o.id===79);
elem = {randomProperty1: "lulu"}

但这显然不起作用,因为它现在是按值调用,而不是按引用调用。

我想出的最后一个(有点难看)的方法是像这样完全改变我的数组:

var array2 = [{obj: {id: 8, text: "lala"}},/* a lot of elements in between,*/ {obj: {id: 79, text: "lolo"}}];
const elem = array2.find(o=>o.obj.id===79);
elem.obj = {randomProperty1: "lulu"}

简而言之:有更好的方法吗?

PS:我不知道标签'vue-reactivity fit's here' - 我不知道这是 angular 中的东西还是因为我不知道对那些一无所知。我的问题只是来自 vue-reactivity,但我认为它可以被推广。

使用findIndex()代替find()

const index = array1.findIndex(o => o.id === 79);
if (index > -1) {
    array1[index] = {randomProperty1: "lulu"};
}

顺便说一句,新对象不应该有一个 id 属性 吗?

您不需要检查索引是否为-1。如果它是-1,当你使用你的数组时,它不会出现,你只能在你使用array1[-1]时访问它,但如果你只是控制台日志array1,它会跳过-1索引

var array1 = [{id: 8, text: "lala"},{id: 9, text: "lela"},{id: 10, text: "lale"},{id: 11, text: "lalala"}, {id: 79, text: "lolo"}]

array1[array1.findIndex(obj => obj.id === 79)] = {randomProperty1: 'lulu'}

当性能是重中之重时,我使用的一个技巧是将数据存储在一个具有数字 ID 数组的对象中,以跟踪所有内容。

与您相似的示例:

var arr = [
 { id: 1, text: 'aaa' },
 { id: 2, text: 'bbb' },
 { id: 3, text: 'ccc' },
 { id: 78, text: 'zzz' }
];

var lookup = arr.reduce((prev, next) => {
  prev[next.id] = next;
  prev.allIds.push(next.id);
  return prev;
}, { allIds: [] });

现在,如果您知道要替换的 ID,则根本不需要循环

lookup[78] = { id: 78, text: 'new!' };

如果你想遍历数组使用allIds 属性

lookup.allIds.forEach(x=> {
  let item = lookup[x];
  item.text = '';
});