Статьи

Совет: как создавать и манипулировать массивами в JavaScript

Эта статья была рецензирована Крисом Перри и Марчелло Ла Рокка . Спасибо всем рецензентам SitePoint за то, что сделали контент SitePoint как можно лучше!

Свойство length объектов Array является тем, что многие, кто относительно новичок в JavaScript, не понимают. Многие ошибочно полагают, что длина говорит вам точно, сколько записей в массиве, тогда как это верно только для некоторых массивов. Некоторые новички даже не осознают, что length — это свойство записи массивов. Чтобы выяснить, как именно работает свойство length , давайте посмотрим, что происходит, когда мы сами изменяем его значение или запускаем что-то, что обновляет массив, что также приводит к изменению длины.

Давайте начнем с самого начала. Массив JavaScript имеет свойство с именем length и может иметь пронумерованные свойства с именами от 0 до 4294967294 включительно. Он также имеет ряд методов для манипулирования свойствами, некоторые из которых мы рассмотрим как часть нашего исследования того, как работает свойство длины. Обратите внимание, что JavaScript не поддерживает ассоциативные массивы, поэтому, хотя вы можете добавлять именованные свойства в массив, они не образуют часть массива и будут игнорироваться всеми методами массива. Они также не влияют на длину.

Чтобы было проще показать, что именно происходит со свойствами массива при обработке различных операторов, мы будем запускать следующую функцию после каждого фрагмента кода. Это запишет длину массива и все пронумерованные свойства в консоль браузера.

 var test = function(array) { console.log('length:'+ array.length); array.forEach(function(element, index, array) { console.log(index + ':' + element); }); }; 

Создание массива

Мы начнем с рассмотрения различных способов создания массива в JavaScript. Первые два из этих примеров создают массивы, в которых задана только длина, а нумерованных записей нет вообще. Вторые два создают пронумерованные записи от 0 до одного, меньшего, чем длина.

Массив, длина которого превышает количество пронумерованных свойств, называется разреженным массивом, а массив с длиной, равной количеству пронумерованных свойств, является плотным массивом .

 //Creates an array with no numbered entries var arr = new Array(5); test(arr); // length: 5 var arr = []; arr.length = 5; test(arr); // length: 5 

Обратите внимание, что литеральная запись массива (где вы определяете новый массив, используя только пустые скобки) предпочтительнее при создании новых массивов.

 var arr = ['a', 'b', 'c', 'd', 'e']; test(arr); // length:5, 0:a, 1:b, 2:c, 3:d, 4:e var arr = [undefined, undefined, undefined, undefined, undefined]; test(arr); // length:5, 0:undefined, 1:undefined, 2:undefined, 3:undefined, 4:undefined 

Методы массива, которые обрабатывают пронумерованные свойства (в нашем случае forEach ), будут обрабатывать только те, которые существуют. Если вместо этого вы обрабатываете массив с помощью цикла for или while, тогда цикл также попытается обработать те свойства, которые не существуют, и массив идентифицирует те записи, которые не существуют, как undefined . Ваш код не сможет различить последний из приведенных выше примеров и первые два. Вы всегда должны использовать методы массива для обработки массива, когда вы не уверены, что имеете дело с плотным массивом.

Изменение длины

В следующих примерах рассматривается, что произойдет, если мы установим новую длину для массива, которая меньше текущей длины.

 var arr = ['a', 'b', 'c', 'd', 'e', 'f']; test(arr); // length:6, 0:a, 1:b, 2:c, 3:d, 4:e, 5:f arr.length = 5; test(arr); // length:5, 0:a, 1:b, 2:c, 3:d, 4:e var arr = ['a','b','c','d','e','f',,,]; test(arr); // length:8, 0:a, 1:b, 2:c, 3:d, 4:e, 5:f arr.length = 7; test(arr); // length:7, 0:a, 1:b, 2:c, 3:d, 4:e, 5:f 

Обратите внимание, что при создании массива с использованием нотации [] каждая запись состоит из значения, за которым следует запятая. Если значение опущено, то для этой позиции не создается никакого свойства. Последняя запятая может быть опущена, только если для этого свойства задано значение, иначе длина будет уменьшена на единицу.

Удаление записей

JavaScript предоставляет три метода pop , shift и splice, которые могут удалять записи из массива и, следовательно, уменьшать длину массива. В каждом случае удаленное значение (или значения) возвращаются вызовом.

 // pop() removes the last element from an array var arr = ['a','b','c','d','e','f']; var el = arr.pop(); test(arr); // length:5, 0:a, 1:b, 2:c, 3:d, 4:e console.log(el); // f // shift() removes the first element from an array var arr = ['a','b','c','d','e','f']; var el = arr.shift(); test(arr); // length:5, 0:b, 1:c, 2:d, 3:e, 4:f console.log(el); // a // splice() can remove existing elements var arr1 = ['a','b','c','d','e','f']; var arr2 = arr1.splice(0,2); // remove 2 elements starting at index 0 test(arr1); // length:4, 0:c, 1:d, 2:e, 3:f test(arr2); // length:2, 0:a, 1:b var arr1 = ['a','b','c','d','e','f',,,'i']; var arr2 = arr1.splice(6,2); // remove 2 elements starting at index 6 test(arr1); // length:7, 0:a, 1:b, 2:c, 3:d, 4:e, 5:f, 6:i test(arr2); // length:2 

Добавление записей

Мы можем добавить новую запись в массив, просто указав позицию в массиве, для которой нумерованное свойство еще не существует. Мы также можем использовать один из трех методов, которые предоставляет JavaScript ( push , unshift и splice ) для вставки новых записей и, при необходимости, перемещения старых.

 var arr = ['a','b','c','d','e','f',,,'i']; arr[11] = 'l'; test(arr); // length:12, 0:a, 1:b, 2:c, 3:d, 5:f, 8:i, 11:l // push() adds one or more elements to the end of an array var arr = ['a','b','c','d','e','f',,,,]; arr.push('j'); test(arr); // length:10, 0:a, 1:b, 2:c, 3:d, 5:f, 9:j // unshift() adds one or more elements to the beginning of an array var arr = ['a','b','c','d','e','f',,,,]; arr.unshift('x'); test(arr); // length:10, 0:x, 1:a, 2:b, 3:c, 4:d, 5:e, 6:f arr1 = ['a','b','c','d','e','f',,,'i']; arr2 = arr1.splice(6,0,'g','h'); // removes 0 elements from index 6, and inserts 'g', 'h' test(arr1); // length:11, 0:a, 1:b, 2:c, 3:d, 5:f, 6:g, 7:h, 10:i test(arr2); // length:0 

Замена записей

Когда мы присваиваем новое значение уже существующей записи, эта запись просто получает новое значение, а остальная часть массива остается неизменной. Также, комбинируя варианты метода splice() которые мы уже рассмотрели, мы можем заменить существующие записи или заполнить пробелы в массиве.

 var arr1 = ['a','b','c','d','e','f',,,'i']; var arr2 = arr1.splice(6,2,'g','h'); test(arr1); // length:9, 0:a, 1:b, 2:c, 3:d, 4:e, 5:f, 6:g, 7:h, 8:i test(arr2); // length:2 

Вывод

Приведенные выше примеры должны были дать вам лучшее представление о том, как работает свойство length массива. Это может быть больше или равно количеству записей в массиве. Там, где он равен, мы имеем плотный массив, а там, где он больше, мы имеем разреженный массив. То, что конкретно делает конкретный метод массива, может зависеть от того, существует ли на самом деле свойство, соответствующее данной позиции в разреженном массиве. Если мы изменим длину массива, он удалит все пронумерованные свойства в массиве, которые находятся в позициях, которые больше новой длины. Если длина была равна количеству пронумерованных свойств, и мы увеличиваем длину, то мы конвертируем плотный массив в разреженный. Методы массива для удаления и добавления свойств в массив будут перемещать существующие записи, где это необходимо, а также сохраняют и перемещают любые промежутки между свойствами.