Отрицательный индекс в JS-массиве: вывод и length
Дан код:
const b = [1, 2, 4];
b["-7"] = 3;
console.log(b); // Первый
console.log(b.length); // Второй
console.log(b.map((item) => item)); // Третий
b.forEach((item) => console.log(item)); // Четвёртый
Что выведетcя в console.log-ах?
Теория: массивы и свойства
В JavaScript массив является объектом. Это означает, что у массива существуют:
- Элементы массива по индексам
0,1,2, ... (это «индексные» свойства). - Обычные свойства объекта с любыми строковыми ключами (например,
"foo","-7"и т.д.).
Запись b["-7"] = 3 добавляет (или изменяет) свойство объекта с именем "-7", а не «элемент массива с индексом -7». Отрицательные «индексы» в JavaScript-массивах не являются индексами массива и не участвуют в механике length.
b["2"] и b[2] обращаются к одному и тому же индексному элементу, а b["-7"] — к неиндексному свойству.Что такое «индекс массива»
У массива есть специальное правило: строковый ключ считается индексом массива только если он выглядит как неотрицательное целое число в канонической форме (например, "0", "1", "2", "10").
Строка "-7" этому условию не соответствует, поэтому:
- не изменяет
length, - не участвует в обходах
map(),forEach()как элемент массива, - не отображается как обычный элемент
0..length-1.
Ниже приведён ориентир по ключам:
| Ключ свойства | Считается индексом массива | Влияет на length |
|---|---|---|
"0", "1", "2" | Да | Да (если индекс ≥ текущего length) |
"-7" | Нет | Нет |
"03" | Нет (не канонично) | Нет |
"3.5" | Нет | Нет |
Разбор кода по шагам
Исходный код:
const b = [1, 2, 4];
b["-7"] = 3;
console.log(b); // Первый
console.log(b.length); // Второй
console.log(b.map((item) => item)); // Третий
console.log(b.forEach((item) => console.log(item))); // Четвёртый
Шаг 1: const b = [1, 2, 4];
- Создаются элементы:
b[0] = 1,b[1] = 2,b[2] = 4. b.lengthстановится3(количество позиций до индекса 2 включительно).
Шаг 2: b["-7"] = 3;
- Создаётся обычное свойство объекта-массива: ключ
"-7", значение3. - Элементы
b[0],b[1],b[2]не меняются. b.lengthне меняется, потому что ключ"-7"не индексный.
Состояние можно представить так:
b (Array-объект)
- индексные элементы:
- "0" -> 1
- "1" -> 2
- "2" -> 4
- обычные свойства:
- "-7" -> 3
- length -> 3
Что выведет каждый console.log
Первый: `console.log(b)`
В консоли будет показан массив с тремя элементами и дополнительным свойством "-7".
Часто это выглядит примерно так: [ 1, 2, 4, '-7': 3 ], но точный формат отображения зависит от среды (браузер, Node.js, настройки DevTools).
Важно, что элементы массива остаются [1, 2, 4], а "-7": 3 — именно свойство, а не «вставка» внутрь списка элементов.
Второй: `console.log(b.length)`
Будет выведено 3.length связан с индексными ключами (0..length-1) и не увеличивается от присваивания по неиндексному ключу "-7".
Третий: `console.log(b.map((item) => item))`
Будет выведено [1, 2, 4].map() создаёт новый массив длины b.length и применяет колбэк только к индексным элементам (позициям 0, 1, 2), а свойство "-7" в этот обход не попадает.
Пример того, что делает map() по смыслу:
// Смысловая модель (упрощённо)
const result = [];
for (let i = 0; i < b.length; i++) {
// берётся именно b[i], а не b["-7"]
result[i] = b[i];
}
console.log(result);
Четвёртый: `b.forEach((item) => console.log(item))`
Вызов console.log(item) выведет элементы массива по порядку:
1
2
4
Почему варианты-ловушки неверны
- Варианты с
[3, 1, 2, 4]предполагают «вставку в начало» или «сдвиг элементов», но присваиваниеb["-7"]сдвигов не делает. - Варианты с
length = 4предполагают, что добавилось 4-е индексное значение, но ключ"-7"не индексный. - Варианты, где
map()возвращает... '-7': 3 ..., неверны, потому чтоmap()обходит индексные позиции0..length-1, а не произвольные свойства. - Вариант «Ошибка TypeError» не подходит, потому что операции корректны: присваивание свойства допустимо,
mapиforEachсуществуют у массивов.
Кратко: b["-7"]=3 добавляет неиндексное свойство "-7", поэтому b отображается с этим свойством, length остаётся 3, map() даёт [1,2,4], а forEach() печатает 1 2 4 и возвращает undefined, который выводится внешним console.log.