Мне нужно создать массив, заполненный объектами. Допустим, { foo: 0}. Затем я хочу добавить свойство bar к каждому объекту с разным значением. Например: значение = индекс элемента в массиве.
Это выглядит так
const table = new Array(10).fill({foo: 0});
for (let i = 0; i < table.length; i += 1) {
table[i].bar = i;
}
Я ожидал получить:
[
{ foo: 0, bar: 0 },
{ foo: 0, bar: 1 },
{ foo: 0, bar: 2 },
...
{ foo: 0, bar: 9 }
]
И что у меня получилось:
[
{ foo: 0, bar: 9 },
{ foo: 0, bar: 9 },
{ foo: 0, bar: 9 },
...
{ foo: 0, bar: 9 }
]
Почему он так себя ведет? Где я ошибся?
РЕДАКТИРОВАТЬ Чтобы уточнить
Я не хочу заменять объекты в массиве новым объектом, например table[i] = {foo: 0, bar: i}. Он создает новый объект, который заменяет старый.
Я просто хочу добавить свойства к существующему объекту.
@Miaan Это неверно. Это потому, что массив заполнен одним и тем же объектом, поэтому, когда вы меняете что-либо в массиве, вы меняете их все. Чтобы увидеть эту проблему, цикл не нужен.
Да, Арчер прав.
Я понимаю, что происходит, я просто не умею объяснять
@Miaan Вставьте это в консоль, а затем проверьте результаты ... var table = new Array(10).fill({foo: 0}); table[3].bar = 25; console.info(table); (обратите внимание, что он меняет только одно свойство - никакого отношения к циклам)



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ваш массив имеет ссылку на один единственный объект. Итак, что происходит, вы обновляете один и тот же базовый объект. Если вы знакомы с C, это будет похоже на наличие N указателей на один и тот же базовый объект. Независимо от того, с каким указателем N вы работаете, вы измените базовый базовый объект.
const table = new Array(10)
for (let i = 0; i < table.length; i += 1) {
table[i] = {foo: 0, bar: i}
}
Это создаст новый объект для каждой записи в вашем массиве
Ладно, я понял. Но я не хочу сразу заполнять массив. Я хочу добавить новые свойства к существующим объектам в массиве без изменения других свойств.
@kotlet Создайте массив, как указано выше, просто удалите свойство bar. Затем вы можете добавить и заполнить bar позже, как и ожидалось.
ИМХО, вы ищете что-то вроде этого:
const table = new Array(10);
for (let i = 0; i < table.length; i += 1) {
table[i] = {'foo': 0, 'bar': i};
}
console.info(table)Одно лайнерное решение с использованием ECMAScript-6:
const table = Array.from(new Array(10).keys()).map(e => ({'foo': 0, 'bar': e}))
console.info(table)Array.fill() принимает значение и заполняет им массив.
Поскольку непримитивы (объекты, массивы) передаются по ссылке, модификация любого элемента приведет к изменению и остальных.
Вместо этого вы можете использовать Array.from() и передать объект его функции сопоставления:
const table = Array.from({length:10}, _ => ({foo:0}));
for (let i = 0; i < table.length; i += 1) {
table[i].bar = i;
}
console.info(table);
Причина этого в том, что значение, которое вы привязываете к атрибуту bar, - я, которое в конце цикла равно 9, которое будет привязано к каждому экземпляру цикла.