Подтвердить что ты не робот

Почему литералы Array с запятыми, но без элементов не имеют длины 0?

Я просто играл с некоторыми JS и нашел то, что, как я думал, не произойдет.

var arr = [,];
arr.length // 1
arr[0] // undefined

Кроме того, [,,] имеет длину 2. Если эти массивы не имеют длины 0? Я думал, что запятые используются только для разделения элементов в массиве, так почему же кажется, что запятые считаются элементами в этих конкретных массивах? Имеет ли такое поведение с массивами какое-либо приложение?

4b9b3361

Ответ 1

В литеральном массиве запятая в конце игнорируется, но все остальные запятые разделяют элементы. Если вы опустите значение элемента, оно по умолчанию равно undefined, но элемент все еще существует. Так

[,]

эквивалентно

[undefined,]

что эквивалентно

[undefined]

У этого есть 1 элемент, значение которого undefined.

Аналогично

[,,] = [undefined, undefined, ] = [undefined, undefined]

который имеет 2 элемента.

Поведение элемента по умолчанию более полезно, если вы хотите опустить элементы в середине массива.

[1, 2, 3, , , 6, 7, 8]

На самом деле существует небольшая разница между двумя способами создания элементов undefined. В Javascript массив фактически является объектом, обладающим свойством length и свойствами, именами которых являются индексы элементов массива. Обычно, если массив имеет length = N, свойства индекса будут целыми числами от 0 до N-1. Но когда вы опускаете элемент в литерале массива, для этого индекса не создается свойство.

Для большинства целей это отсутствующее свойство не имеет существенного значения, поскольку доступ к несуществующему свойству объекта возвращает undefined, как если бы у вас есть свойство, значение которого undefined. Эти недостающие свойства можно обнаружить только с помощью метода типа hasOwnProperty или вызова Object.keys. Консоль Javascript использует нечто подобное, чтобы отображать пробелы в массиве, отличные от явных элементов undefined.

Итак,

Object.getOwnPropertyNames([1, 2, 3]) => ["0", "1", "2", "length"]
Object.getOwnPropertyNames([1, , 3, 4]) => ["0", "2", "3", "length"]
Object.getOwnPropertyNames([, , , , ]) => ["length"]

Причина игнорирования последней запятой заключается в том, что вы можете написать:

[ 
    "foo",
    "bar",
    "baz",
    "quux",
]

Это упрощает редактирование, потому что вы можете вставлять и удалять строки, не используя специальный элемент последнего элемента.

Ответ 2

Это называется elision. Он создает "дыру" в массиве (разреженный массив). Вероятно, есть приложения, о которых я не знаю и о которых забыл, единственное, о чем я могу сейчас подумать, - это тот, который я показываю здесь: fooobar.com/questions/14948/....

[,...Array(10)].map((x, i) => { /* range of `i` is 1 - 10 */ })

[,,] не эквивалентен [undefined, undefined,]. Существует большая разница: методы итерации не будут включать элементы в индексированных указателях. Пример:

var enumerated = [];

function callback (x, i) {
  enumerated.push(i);
}

[,,].forEach(callback);
console.log(enumerated); // logs []

[undefined, undefined,].forEach(callback);
console.log(enumerated); // logs [1, 2]