Разный результат при одинаковых операциях с массивом объектов
Создаю массив объектов:
const arr1 = [{}, {}, {}, {}];
const arr2 = Array(4).fill({});
Добавляю свойство в объект:
arr1[1].One = '1';
arr2[1].One = '1';
Проверяю arr1:
0: {};
1: {One: '1'};
2: {};
3: {};
Проверяю arr2:
0: {One: '1'};
1: {One: '1'};
2: {One: '1'};
3: {One: '1'};
Почему так?
Ответы (2 шт):
Array(4).fill({}) создаст массив с 4 элементами и в каждый положит ссылку на ОДИН объект.
Т.к. объекты передаются по ссылкам, то присваивание одного объекта разным переменным делает эти переменные равными друг-другу. Другими словами, все такие переменные смотрят на один объект.
Проверить можно на примере ниже:
const a = { one: 2 }
const b = a; // Передали по ссылке. b теперь ссылается на a
b.one = 1;
console.log('Равны', a === b);
console.log(a, b);
const c = { one: 2 };
const d = { one: 2 }; // Cоздали новый объект
console.log('Не равны', c === d);
console.log(c, d);
Зная это, метод fill, в вашем примере, можно представить как:
const obj = {};
array.fill(obj);
Метод fill сначала получает значение, которое надо присвоить элементам и уже потом выполняет операцию присваивания. Поэтому получаем вот такой массив
[obj, obj, obj, obj]
Убедиться в этом можно так:
const arr2 = Array(4).fill({});
console.log(arr2[1] === arr2[3]); // Все элементы равны друг другу, т.к. объект один
arr2[3].one = 1;
console.log(arr2[1] === arr2[3]);
console.log(arr2[0], arr2[1], arr2[2], arr2[3]);
Метод fill() заполняет все элементы массива от начального до конечного индексов одним значением.
Когда ты записываешь в переменную объект, ты записываешь ссылку на этот объект, а не сам объект. Соответственно, при копировании данных из одной переменной в другую переменную, будет копироваться ссылка, а не объект. А это значит, что при редактировании "скопированного" объекта будет редактироваться и первоначальный, так как обе переменных ссылаются на один объект
const a = {}
const b = a;
b.field = 1;
console.log(a) // {field : 1}
В функции fill() происходит примерно то же самое:
const array = [];
const argument = {}; // объект, переданный в функцию
// Всем полям задаётся одна и та же ссылка на объект, объект при этом не копируется
array[0] = argument;
array[1] = argument;
array[2] = argument;
array[3] = argument;
array[0].field = 1
console.log(array) // [{field: 1}, {field: 1}, {field: 1}, {field: 1}]
А когда ты сам инициализируешь массив объектами, ты создаёшь 4 разных объекта, не зависящих друг от друга