Источник: http://bonsaiden.github.io/JavaScript-Garden/ru/#array
Несмотря на то, что массивы в JavaScript являются объектами, нет достаточных оснований для использования цикла for in
для итерации по элементам массива. Фактически, существует несколько весомых причин против использования for in
в массивах.
Замечание: Массивы в JavaScript не являются ассоциативными массивами. Для связывания ключей и значений в JavaScript есть только объекты. И при том, что ассоциативные массивы сохраняют заданный порядок, объекты не делают этого.
Во время выполнения for in
циклически перебираются все свойства объекта, находящиеся в цепочке прототипов. Единственный способ исключить ненужные свойства — использовать hasOwnProperty
, а это в 20 раз медленнее обычного цикла for
.
Для достижения лучшей производительности при итерации по массивам, лучше всего использовать обычный цикл for
.
var list = [1, 2, 3, 4, 5, ...... 100000000];
for(var i = 0, l = list.length; i < l; i++) {
console.log(list[i]);
}
В примере выше есть один дополнительный приём, с помощью которого кэшируется величина длины массива: l = list.length
.
Несмотря на то, что свойство length
определено в самом массиве, поиск этого свойства накладывает дополнительные расходы на каждой итерации цикла. Пусть в этом случае новые движки JavaScript теоретически могут применить оптимизацию, но нет никакого способа узнать, будет оптимизирован код на новом движке или нет.
Фактически, отсутствие кэширования может привести к выполнению цикла в два раза медленнее, чем при кэшировании длины.
length
Хотя геттер свойства length
просто возвращает количество элементов содержащихся в массиве, сеттер можно использовать для обрезания массива.
var foo = [1, 2, 3, 4, 5, 6];
foo.length = 3;
foo; // [1, 2, 3]
foo.length = 6;
foo; // [1, 2, 3]
Присвоение свойству length
меньшей величины урезает массив, однако присвоение большего значения не даст никакого эффекта.
Для оптимальной работы кода рекомендуется всегда использовать простой цикл for
и кэшировать свойство length
. Использование for in
с массивами является признаком плохого кода, обладающего предпосылками к ошибкам и может привести к низкой скорости его выполнения.
Array
Так как в конструкторе Array
есть некоторая двусмысленность, касающаяся его параметров, настоятельно рекомендуется при создании массивов всегда использовать синтаксис литеральной нотации — []
.
[1, 2, 3]; // Результат: [1, 2, 3]
new Array(1, 2, 3); // Результат: [1, 2, 3]
[3]; // Результат: [3]
new Array(3); // Результат: []
new Array('3') // Результат: ['3']
В случае, когда в конструктор Array
передаётся один аргумент и этот аргумент имеет тип Number
, конструктор возвращает новый, заполненный случайными значениями, массив, имеющий длину равную значению переданного аргумента. Стоит заметить, что в этом случае будет установлено только свойство length
нового массива, индексы массива фактически не будут проинициализированы.
var arr = new Array(3);
arr[1]; // не определён, undefined
1 in arr; // false, индекс не был установлен
Поведение, которое позволяет изначально установить только размер массива, может пригодиться лишь в нескольких случаях, таких как повторение строк, за счёт чего избегается использование цикла for loop
.
new Array(count + 1).join(stringToRepeat);
Использование конструктора Array
нужно избегать, насколько это возможно. Литералы определённо предпочтительнее — это краткая запись и она имеет более понятный синтаксис, так что при этом даже улучшается читабельность кода.