【问题标题】:javascript : .filter updating object in original array?javascript:.filter 更新原始数组中的对象?
【发布时间】:2020-03-18 16:10:36
【问题描述】:

我正在为学校创建一个小游戏,我正在创建一个由 100 个图块组成的棋盘,它们是 JS 对象。其中一些瓷砖被随机阻挡(这是它们的属性之一)。玩家不能进去。

我还需要在这些图块上随机放置 4 把武器。

所以我创建了一系列未阻挡的图块,然后我将我的武器一个一个地放在这些空闲的图块上。为了确保其中一个图块上没有武器,我使用 .filter() 创建了一个新的未阻塞且空的图块数组(没有武器)。

问题是,当我在我的新数组中更新一个图块的属性时(发出 .filter,以确保不会有两个武器在同一个位置),它会更新图块的属性父数组,我不明白这一点。我读过 .filter() 方法不更新父数组,但在这里它可以吗? 也许是因为它是一个 JS 对象?

感谢您的澄清!

let tilesUnblocked = []
//here function creating tiles and pushing unblocked tiles in the array above
for (i = 0; i < weapons.length; i++) {
    let tilesUnblockedAndEmpty = tilesUnblocked.filter(tile => tile.weapon === false) 
    let randomInt = Math.round(tilesUnblockedAndEmpty.length * Math.random())
    let weaponElt = weapons[i].HTMLElement
    weaponElt.css({ //some css })
    tilesUnblockedAndEmpty[randomInt].HTMLElement.append(weaponElt)
    tilesUnblockedAndEmpty[randomInt].weapon = true //updating array created from filter
    tilesUnblockedAndEmpty[randomInt].weaponType = weapons[i].name //updating array created from filter
}
console.log(tilesUnblocked) //I will find in this array the objects updated at the end of the foor loop, on the array issued of .filter method !

【问题讨论】:

  • .filter() 创建一个新数组,但不是所有对象的新副本。这两个数组共享对相同对象的引用。
  • 在 filter func try .map(item => {...item}) 之后,这将创建新对象并用相同的对象但不同的引用填充新数组

标签: javascript arrays object for-loop filter


【解决方案1】:

也许是因为它是一个 JS 对象?

是的。如果你有这个:

const original = [
    {example: 42},
    {example: 21}
];

你的记忆中有这样的东西:

+−−−−−−−−−−−+ 原创------>| (数组) | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−+ | 0 |−−−−−−−−−->| (对象) | | 1 |−−+ +−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | |示例:42 | | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−−−−−−−>| (对象) | +−−−−−−−−−−−−−−+ |示例:21 | +−−−−−−−−−−−−−−+

如果你这样做:

const filtered = original.filter(entry => entry.example !== 42);

你有:

+−−−−−−−−−−−+ 原创------>| (数组) | +−−−−−−−−−−+ +−−−−−−−−−−−−−−−+ | 0 |−−−−−−−−−->| (对象) | | 1 |−−+ +−−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | |示例:42 | | +−−−−−−−−−−−−−−+ | +−−−−−−−−−−−−−−+ +−−−−−−−>| (对象) | | +−−−−−−−−−−−−−−+ | |示例:21 | | +−−−−−−−−−−−−−−+ +−−−−−−−−−−+ | 过滤了−−−−−−>| (数组) | | +−−−−−−−−−−+ | | 0 |−−+ +−−−−−−−−−−−+

如您所见,两个数组都指向相同的对象。如果您更改该对象的状态(例如,通过添加或更改属性),则该更改在两个数组中都是可见的。

如果您希望过滤后的数组具有副本,您必须明确地这样做:

const filtered = original
    .filter(entry => entry.example !== 42)
    .map(entry => ({...entry});

这只是复制对象的一种方法,this question 的答案中还涵盖了更多方法。

【讨论】:

    【解决方案2】:

    尝试在过滤之前复制您的对象:

    let tilesUnblockedAndEmpty = tilesUnblocked.map(e => Object.assign({}, e)).filter(tile => tile.weapon === false)
    

    这应该可行,具体取决于对象的外观。 JSON.stringify 后跟 JSON.parse 是一种更复杂的方法,可以处理更多用例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-04
      • 2021-12-17
      • 2011-07-01
      • 1970-01-01
      • 2019-10-01
      • 2021-11-27
      相关资源
      最近更新 更多