Конспект JS-course

JavaScript Garden. Массивы

Источник: 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 нужно избегать, насколько это возможно. Литералы определённо предпочтительнее — это краткая запись и она имеет более понятный синтаксис, так что при этом даже улучшается читабельность кода.