javascript: .filter обновляет объект в исходном массиве? - PullRequest
0 голосов
/ 18 марта 2020

Я создаю небольшую игру для школы и создаю доску из 100 плиток, которые являются JS объектами. Некоторые из этих плиток блокируются (это одно из их свойств) случайным образом. Игрок не может go в нем.

Мне нужно положить 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 !

Ответы [ 2 ]

2 голосов
/ 18 марта 2020

Может быть, это потому, что это 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       |−−+
               +−−−−−−−−−+

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

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

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

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

0 голосов
/ 18 марта 2020

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...