Лекция
Привет, сегодня поговорим про массивы c числовыми индексами, обещаю рассказать все что знаю. Для того чтобы лучше понимать что такое массивы c числовыми индексами , настоятельно рекомендую прочитать все из категории Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend).
pop/push
, shift/unshift
length
length
для укорачивания массиваnew Array
new Array()
Массив с числовыми индексами - это коллекция данных, которая хранит сколько угодно значений, причем у каждого значения - свой уникальный номер.
Если переменная — это коробка для данных, то массив — это шкаф с нумерованными ячейками, в каждой из которых могут быть свои данные.
Например, при создании электронного магазина нужно хранить список товаров — для таких задач и придуман массив.
Синтаксис для создания нового массива — квадратные скобки со списком элементов внутри.
Пустой массив:
var arr = []; |
Массив fruits
с тремя элементами:
var fruits = [ "Яблоко" , "Апельсин" , "Слива" ]; |
Элементы нумеруются, начиная с нуля. Чтобы получить нужный элемент из массива — указывается его номер в квадратных скобках:
1 |
var fruits = [ "Яблоко" , "Апельсин" , "Слива" ]; |
2 |
3 |
alert(fruits[0]); // Яблоко |
4 |
alert(fruits[1]); // Апельсин |
5 |
alert(fruits[2]); // Слива |
Элемент можно всегда заменить:
fruits[2] = 'Груша' ; // теперь ["Яблоко", "Апельсин", "Груша"] |
fruits[3] = 'Лимон' ; // теперь ["Яблоко", "Апельсин", "Груша", "Лимон"] |
Общее число элементов, хранимых в массиве, содержится в его свойстве length
:
1 |
var fruits = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
alert(fruits.length); // 3 |
Через alert
можно вывести и массив целиком. При этом его элементы будут перечислены через запятую:
1 |
var fruits = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
alert(fruits); // Яблоко,Апельсин,Груша |
В массиве может храниться любое число элементов любого типа. В том числе, строки, числа, объекты и т.п.:
1 |
// микс значений |
2 |
var arr = [ 1, 'Имя' , { name: 'Петя' }, true ]; |
3 |
4 |
// получить объект из массива и тут же -- его свойство |
5 |
alert( arr[2].name ); // Петя |
pop/push
, shift/unshift
Одно из применений массива — это очередь. В классическом программировании так называют упорядоченную коллекцию элементов, такую что элементы добавляются в конец, а обрабатываются — с начала.
В реальной жизни эта структура данных встречается очень часто. Например, очередь сообщений, которые надо отослать.
Очень близка к очереди еще одна структура данных: стек. Это такая коллекция элементов, в которой новые элементы добавляются в конец и берутся с конца.
Например, стеком является колода карт, в которую новые карты кладутся сверху, и берутся — тоже сверху.
Для того, чтобы реализовывать эти структуры данных, и просто для более удобной работы с началом и концом массива существуют специальные методы.
pop
1 |
var fruits = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
alert( fruits.pop() ); // удалили "Груша" |
4 |
5 |
alert(fruits); // Яблоко, Апельсин |
push
1 |
var fruits = [ "Яблоко" , "Апельсин" ]; |
2 |
3 |
fruits.push( "Груша" ); |
4 |
5 |
alert(fruits); // Яблоко, Апельсин, Груша |
Является полным аналогом fruits[fruits.length] = ...
.
shift
1 |
var fruits = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
alert( fruits.shift() ); // удалили Яблоко |
4 |
5 |
alert(fruits); // Апельсин, Груша |
unshift
1 |
var fruits = [ "Апельсин" , "Груша" ]; |
2 |
3 |
fruits.unshift( 'Яблоко' ); |
4 |
5 |
alert(fruits); // Яблоко, Апельсин, Груша |
Методы push
и unshift
могут добавлять сразу по несколько элементов:
1 |
var fruits = [ "Яблоко" ]; |
2 |
3 |
fruits.push( "Апельсин" , "Персик" ); |
4 |
fruits.unshift( "Ананас" , "Лимон" ); |
5 |
6 |
// результат: ["Ананас", "Лимон", "Яблоко", "Апельсин", "Персик"] |
7 |
alert(fruits); |
Массив — это объект, где в качестве ключей выбраны цифры, с дополнительными методами и свойством length
.
Так как это объект, то в функцию он передается по ссылке:
01 |
function eat(arr) { |
02 |
arr.pop(); |
03 |
} |
04 |
05 |
var arr = [ "нам" , "не" , "страшен" , "серый" , "волк" ] |
06 |
07 |
alert(arr.length); // 5 |
08 |
eat(arr); |
09 |
eat(arr); |
10 |
alert(arr.length); // 3, в функцию массив не скопирован, а передана ссылка |
Еще одно следствие — можно присваивать в массив любые свойства.
Например:
1 |
var fruits = []; // создать массив |
2 |
3 |
fruits[99999] = 5; // присвоить свойство с любым номером |
4 |
5 |
fruits.age = 25; // назначить свойство со строковым именем |
.. Об этом говорит сайт https://intellect.icu . Но массивы для того и придуманы в JavaScript, чтобы удобно работать именно с упорядоченными, нумерованными данными. Для этого в них существуют специальные методы и свойство length
.
Как правило, нет причин использовать массив как обычный объект, хотя технически это и возможно.
Если в массиве есть пропущенные индексы, то при выводе в большинстве браузеров появляются «лишние» запятые, например:
1 |
var a = []; |
2 |
a[0] = 0; |
3 |
a[5] = 5; |
4 |
5 |
alert(a); // 0,,,,,5 |
Эти запятые появляются потому, что алгоритм вывода массива идет от 0
доarr.length
и выводит все через запятую. Отсутствие значений дает несколько запятых подряд.
Методы push/pop
выполняются быстро, а shift/unshift
— медленно.
Чтобы понять, почему работать с концом массива — быстрее, чем с его началом, разберем происходящее подробнее.
Операция shift
выполняет два действия:
length
.При этом, так как все элементы находятся в своих ячейках, просто очистить ячейку с номером 0
недостаточно. Нужно еще и переместить все ячейки на 1
вниз (красным на рисунке подсвечены изменения):
fruits.shift(); // убрать 1 элемент с начала |
Чем больше элементов в массиве, тем дольше их перемещать.
Аналогично работает unshift
: чтобы добавить элемент в начало массива, нужно сначала перенести все существующие.
У методов push/pop
таких проблем нет. Для того, чтобы удалить элемент, метод pop
очищает ячейку и укорачивает length
.
fruits.pop(); // убрать 1 элемент с конца |
Аналогично работает push
.
Для перебора элементов обычно используется цикл:
1 |
var arr = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
for ( var i=0; i<arr.length; i++) { |
4 |
alert( arr[i] ); |
5 |
} |
for..in
для массивовТак как массив является объектом, то возможен и вариант for..in
:
1 |
var arr = [ "Яблоко" , "Апельсин" , "Груша" ]; |
2 |
3 |
for ( var key in arr) { |
4 |
alert( arr[key] ); // Яблоко, Апельсин, Груша |
5 |
} |
Недостатки этого способа:
for..in
выведет все свойства объекта, а не только цифровые.
В браузере, при работе с объектами страницы, встречаются коллекции элементов, которые по виду как массивы, но имеют дополнительные нецифровые свойства, которые будут видны в цикле for..in
.
Бывают и библиотеки, которые предоставляют такие коллекции. Например jQuery. С виду — массив, но есть дополнительные свойства. Для перебора только цифровых свойств нужен цикл for(var i=0; i<arr.length...)
for (var i=0; i<arr.length; i++)
в современных браузерах выполняется в 10-100 раз быстрее. Казалось бы, по виду он сложнее, но браузер особым образом оптимизирует такие циклы.Если кратко: цикл for(var i=0; i<arr.length...)
надежнее и быстрее.
length
Встроенные методы для работы с массивом автоматически обновляют его длину length
.
Длина length
— не количество элементов массива, а последний индекс + 1
. Так уж оно устроено.
Это легко увидеть на следующем примере:
1 |
var arr = []; |
2 |
arr[1000] = true ; |
3 |
4 |
alert(arr.length); // 1001 |
Вообще, если у вас элементы массива нумеруются случайно или с большими пропусками, то стоит подумать о том, чтобы использовать обычный объект.
Массивы предназначены именно для работы с непрерывной упорядоченной коллекцией элементов.
length
для укорачивания массиваОбычно нам не нужно самостоятельно менять length
… Но есть один фокус, который можно провернуть.
При уменьшении length
массив укорачивается. Причем этот процесс необратимый, т.е. даже если потом вернуть length
обратно — значения не восстановятся:
1 |
var arr = [1, 2, 3, 4, 5]; |
2 |
3 |
arr.length = 2; // укоротить до 2 элементов |
4 |
alert(arr); // [1, 2] |
5 |
6 |
arr.length = 5; // вернуть length обратно, как было |
7 |
alert(arr[3]); // undefined: значения не вернулись |
Самый простой способ очистить массив — это arr.length=0
.
new Array
new Array()
Существует еще один синтаксис для создания массива:
var arr = new Array ( "Яблоко" , "Груша" , "и т.п." ); |
Он редко используется, т.к. квадратные скобки []
короче.
Кроме того, у него есть одна особенность. Обычно new Array(элементы, ...)
создает массив из данных элементов, но если у него один аргумент, и это число —то он создает массив без элементов, но с заданной длиной.
1 |
var arr = new Array(2,3); // создает массив [2, 3] |
2 |
3 |
arr = new Array(2); // создаст массив [2] ? |
4 |
5 |
alert(arr[0]); // нет! у нас массив без элементов, длины 2 |
Что же такое этот «массив без элементов, но с длиной»? Как такое возможно?
Оказывается, очень даже возможно и соответствует объекту {length: 2}
. Получившийся массив ведет себя так, как будто его элементы равны undefined
.
Это может быть неожиданным сюрпризом, поэтому обычно используют квадратные скобки.
Массивы в JavaScript могут содержать в качестве элементов другие массивы. Это можно использовать для создания многомерных массивов, например матриц:
1 |
var matrix = [ |
2 |
[1, 2, 3], |
3 |
[4, 5, 6], |
4 |
[7, 8, 9] |
5 |
]; |
6 |
7 |
alert(matrix[1][1]); // центральный элемент |
Эта секция относится ко внутреннему устройству структуры данных и требует специальных знаний. Она не обязательна к прочтению.
Числовые массивы, согласно спецификации, являются объектами, в которые добавили ряд свойств, методов и автоматическую длину length
. Но внутри они, как правило, устроены по-другому.
Современные интерпретаторы стараются оптимизировать их и хранить в памяти не в виде хэш-таблицы, а в виде непрерывной области памяти, так же как в языке C. Операции с массивами также оптимизируются, особенно если массив хранит только один тип данных, например только числа. Порождаемый набор инструкций для процессора получается очень эффективным.
Как правило, у интерпретатора это получается, но при этом программист не должен мешать.
В частности:
arr.test = 5
. То есть, работать именно как с массивом, а не как с объектом.arr[0]
, а потом сразу arr[1000]
, то он начинает работать с ним, как с обычным объектом. Как правило, это влечет преобразование его в хэш-таблицу.Если следовать этим принципам, то массивы будут занимать меньше памяти и быстрее работать.
Массивы существуют для работы с упорядоченным набором элементов.
Объявление:
1 |
// предпочтительное |
2 |
var arr = [ элемент1, элемент2... ]; |
3 |
4 |
// new Array |
5 |
var arr = new Array( элемент1, элемент2...); |
При этом new Array(число)
создает массив заданной длины, без элементов. Чтобы избежать ошибок, предпочтителен первый синтаксис.
Свойство length
— длина массива. Если точнее, то последний индекс массива плюс 1
. Если ее уменьшить вручную, то массив укоротится. Если length
больше реального количества элементов, то отсутствующие элементы равны undefined
.
Массив можно использовать как очередь или стек.
Операции с концом массива:
arr.push(элемент1, элемент2...)
добавляет элементы в конец.var elem = arr.pop()
удаляет и возвращает последний элемент.Операции с началом массива:
arr.unshift(элемент1, элемент2...)
добавляет элементы в начало.var elem = arr.shift()
удаляет и возвращает первый элемент.Эти операции перенумеровывают все элементы, поэтому работают медленно.
В следующей главе мы рассмотрим другие методы для работы с массивами.
Комментарии
Оставить комментарий
Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)
Термины: Выполнение скриптов на стороне клиента JavaScript, jqvery, JS фреймворки (Frontend)