Я создаю небольшую игру для школы и создаю доску из 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 !
0
troadecnicolas 18 Мар 2020 в 19:10

2 ответа

Лучший ответ

Может быть, это потому, что это объект JS?

Да. Если у вас есть это:

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

У вас есть что-то подобное в памяти:

               +−−−−−−−−−+
original−−−−−−>| (array) |
               +−−−−−−−−−+          +−−−−−−−−−−−−−+
               | 0       |−−−−−−−−−>|  (object)   |
               | 1       |−−+       +−−−−−−−−−−−−−+
               +−−−−−−−−−+  |       | example: 42 |
                            |       +−−−−−−−−−−−−−+
                            |       +−−−−−−−−−−−−−+
                            +−−−−−−>|  (object)   |
                                    +−−−−−−−−−−−−−+
                                    | example: 21 |
                                    +−−−−−−−−−−−−−+

Если вы затем сделаете это:

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

У тебя есть:

               +−−−−−−−−−+
original−−−−−−>| (array) |
               +−−−−−−−−−+          +−−−−−−−−−−−−−+
               | 0       |−−−−−−−−−>|  (object)   |
               | 1       |−−+       +−−−−−−−−−−−−−+
               +−−−−−−−−−+  |       | example: 42 |
                            |       +−−−−−−−−−−−−−+
                            |       +−−−−−−−−−−−−−+
                            +−−−−−−>|  (object)   |
                            |       +−−−−−−−−−−−−−+
                            |       | example: 21 |
                            |       +−−−−−−−−−−−−−+
               +−−−−−−−−−+  |
filtered−−−−−−>| (array) |  |
               +−−−−−−−−−+  |
               | 0       |−−+
               +−−−−−−−−−+

Как видите, оба массива указывают на один и тот же объект. Если вы измените состояние этого объекта (например, добавив или изменив свойство), это изменение будет видно через оба массива.

Если вы хотите, чтобы отфильтрованный массив имел копии , вы должны сделать это явно:

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

Это всего лишь один из способов скопировать объект, еще несколько из них описаны в ответах на этот вопрос.

2
T.J. Crowder 18 Мар 2020 в 16:18

Попробуйте сделать копию ваших объектов перед фильтрацией:

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

Это должно работать, в зависимости от того, как выглядят объекты. JSON.stringify, за которым следует JSON.parse, является хакерским методом, который будет обрабатывать больше вариантов использования.

0
Mitch Lillie 18 Мар 2020 в 16:18