Array

 

Массив (Array) в JavaScript является глобальным объектом, который используется для создания массивов; которые представляют собой высокоуровневые спископодобные объекты.

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

var fruits = ['Яблоко', 'Банан'];

console.log(fruits.length);
// 2

Доступ к элементу массива по индексу

var first = fruits[0];
// Яблоко

var last = fruits[fruits.length - 1];
// Банан

Итерирование по массиву

fruits.forEach(function(item, index, array) {
  console.log(item, index);
});
// Яблоко 0
// Банан 1

Добавление элемента в конец массива

var newLength = fruits.push('Апельсин');
// ["Яблоко", "Банан", "Апельсин"]

Удаление последнего элемента массива

var last = fruits.pop(); // удалим Апельсин (из конца)
// ["Яблоко", "Банан"];

Удаление первого элемента массива

var first = fruits.shift(); // удалим Яблоко (из начала)
// ["Банан"];

Добавление элемента в начало массива

var newLength = fruits.unshift('Клубника') // добавляет в начало
// ["Клубника", "Банан"];

Поиск номера элемента в массиве

fruits.push('Манго');
// ["Клубника", "Банан", "Манго"]

var pos = fruits.indexOf('Банан');
// 1

Удаление элемента с определённым индексом

var removedItem = fruits.splice(pos, 1); // так можно удалить элемент

// ["Клубника", "Манго"]

Удаление нескольких элементов, начиная с определённого индекса

var vegetables = ['Капуста', 'Репа', 'Редиска', 'Морковка'];
console.log(vegetables);
// ["Капуста", "Репа", "Редиска", "Морковка"]

var pos = 1, n = 2;

var removedItems = vegetables.splice(pos, n);
// так можно удалить элементы, n определяет количество элементов для удаления,
// начиная с позиции(pos) и далее в направлении конца массива.

console.log(vegetables);
// ["Капуста", "Морковка"] (исходный массив изменён)

console.log(removedItems);
// ["Репа", "Редиска"]

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

var shallowCopy = fruits.slice(); // так можно создать копию массива
// ["Клубника", "Манго"]

Синтаксис

[element0, element1, ..., elementN]
new Array(element0, element1[, ...[, elementN]])
new Array(arrayLength)
elementN
Массив в JavaScript инициализируется с помощью переданных элементов, за исключением случая, когда в конструктор Array передаётся один аргумент и этот аргумент является числом (см. ниже). Стоит обратить внимание, что этот особый случай применяется только к JavaScript-массивам, создаваемым с помощью конструктора Array, а не к литеральным массивам, создаваемым с использованием скобочного синтаксиса.
arrayLength
Если конструктору Array передаётся единственный аргумент, являющийся целым числом в диапазоне от 0 до 232-1 (включительно), будет возвращён новый пустой JavaScript-массив, длина которого установится в это число (примечание: это означает массив, содержащий arrayLength пустых ячеек, а не ячеек со значениями undefined). Если аргументом будет любое другое число, возникнет исключение RangeError.

Описание

Массивы являются спископодобными объектами, чьи прототипы содержат методы для операций обхода и изменения массива. Ни размер JavaScript-массива, ни типы его элементов не являются фиксированными. Поскольку размер массива может увеличиваться и уменьшаться в любое время, то нет гарантии, что массив окажется плотным. То есть, при работе с массивом может возникнуть ситуация, что элемент массива, к которому вы обратитесь, будет пустым и вернёт undefined. В целом, это удобная характеристика; но если эта особенность массива не желательна в вашем специфическом случае, вы можете рассмотреть возможность использования типизированных массивов.

Некоторые полагают, что вы не должны использовать массив в качестве ассоциативного массива. В любом случае, вместо него вы можете использовать простые объекты, хотя у них есть и свои подводные камни. Смотрите пост Легковесные JavaScript-словари с произвольными ключами(англ.) в качестве примера.

Доступ к элементам массива

Массивы в JavaScript индексируются с нуля: первый элемент массива имеет индекс, равный 0, а индекс последнего элемента равен значению свойства массива length минус 1.

var arr = ['первый элемент', 'второй элемент', 'последний элемент'];
console.log(arr[0]);              // напечатает 'первый элемент'
console.log(arr[1]);              // напечатает 'второй элемент'
console.log(arr[arr.length - 1]); // напечатает 'последний элемент'

Элементы массива являются свойствами, точно такими же, как, например, свойство toString, однако попытка получить элемент массива по имени его свойства приведёт к синтаксической ошибке, поскольку имя свойства не является допустимым именем JavaScript:

console.log(arr.0); // синтаксическая ошибка

Это не особенность массивов или их свойств. В JavaScript к свойствам, начинающимся с цифры, невозможно обратиться посредством точечной нотации; к ним можно обратиться только с помощью скобочной нотации. Например, если у вас есть объект со свойством, названным '3d', вы сможете обратиться к нему только посредством скобочной нотации. Примеры:

var years = [1950, 1960, 1970, 1980, 1990, 2000, 2010];
console.log(years.0);   // синтаксическая ошибка
console.log(years[0]);  // работает как положено
renderer.3d.setTexture(model, 'character.png');     // синтаксическая ошибка
renderer['3d'].setTexture(model, 'character.png');  // работает как положено

Обратите внимание, что во втором примере 3d заключено в кавычки: '3d'. Индексы можно заключать в кавычки (например years['2'] вместо years[2]), но в этом нет необходимости. Значение 2 в выражении years[2] будет неявно приведено к строке движком JavaScript через метод преобразования toString. Именно по этой причине ключи '2' и '02' будут ссылаться на два разных элемента в объекте years и следующий пример выведет true:

console.log(years['2'] != years['02']);

Аналогично, к свойствам объекта, являющимся зарезервированными словами(!) можно получить доступ только посредством скобочной нотации:

var promise = {
  'var'  : 'text',
  'array': [1, 2, 3, 4]
};

console.log(promise['array']);

Взаимосвязь свойства length с числовыми свойствами

Свойство массивов length взаимосвязано с числовыми свойствами. Некоторые встроенные методы массива (например, join, slice, indexOf и т.д.) учитывают значение свойства length при своём вызове. Другие методы (например, push, splice и т.д.) в результате своей работы также обновляют свойство length массива.

var fruits = [];
fruits.push('банан', 'яблоко', 'персик');

console.log(fruits.length); // 3

При установке свойства в массиве, если свойство имеет действительный индекс и этот индекс выходит за пределы текущих границ массива, движок соответствующим образом обновит свойство length:

fruits[5] = 'манго';
console.log(fruits[5]);             // 'манго'
console.log(Object.keys(fruits));   // ['0', '1', '2', '5']
console.log(fruits.length);         // 6

Увеличиваем свойство length

fruits.length = 10;
console.log(Object.keys(fruits));   // ['0', '1', '2', '5']
console.log(fruits.length);         // 10

Однако, уменьшение свойства length приведёт к удалению элементов.

fruits.length = 2;
console.log(Object.keys(fruits)); // ['0', '1']
console.log(fruits.length); // 2

Более подробно эта тема освещена на странице, посвящённой свойству Array.length.

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

Результатом сопоставления регулярного выражения строке является JavaScript-массив. Этот массив имеет свойства и элементы, предоставляющие информацию о сопоставлении. Подобные массивы возвращаются методами RegExp.exec, String.match и String.replace. Чтобы было проще понять, откуда и какие появились свойства и элементы, посмотрите следующий пример и обратитесь к таблице ниже:

// Сопоставляется с одним символом d, за которым следует один
// или более символов b, за которыми следует один символ d
// Запоминаются сопоставившиеся символы b и следующий за ними символ d
// Регистр игнорируется

var myRe = /d(b+)(d)/i;
var myArray = myRe.exec('cdbBdbsbz');

Свойства и элементы, возвращаемые из данного сопоставления, описаны ниже:

Свойство/Элемент Описание Пример
input Свойство только для чтения, отражающее оригинальную строку, с которой сопоставлялось регулярное выражение. cdbBdbsbz
index Свойство только для чтения, являющееся индексом (отсчёт начинается с нуля) в строке, с которого началось сопоставление. 1
[0] Элемент только для чтения, определяющий последние сопоставившиеся символы. dbBd
[1], ...[n] Элементы только для чтения, определяющие сопоставившиеся подстроки, заключённые в круглые скобки, если те включены в регулярное выражение. Количество возможных подстрок не ограничено. [1]: bB
[2]: d

Свойства

Array.length
Значение свойства length конструктора массива равно 1.
Array.prototype
Позволяет добавлять свойства ко всем объектам массива.

Методы

Array.from() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Создаёт новый экземпляр Array из массивоподобного или итерируемого объекта.
Array.isArray()
Возвращает true, если значение является массивом, иначе возвращает false.
Array.observe() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Асинхронно наблюдает за изменениями в массиве, подобно методу Object.observe() для объектов. Метод предоставляет поток изменений в порядке их возникновения.
Array.of() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Создаёт новый экземпляр Array из любого количества аргументов, независимо от их количества или типа.

Экземпляры массива

Все экземпляры массива наследуются от Array.prototype. Изменения в объекте прототипа конструктора массива затронет все экземпляры Array.

Свойства

Array.prototype.constructor
Определяет функцию, создающую прототип объекта.
Array.prototype.length
Отражает количество элементов в массиве.

Методы

Методы изменения

Эти методы изменяют массив:

Array.prototype.copyWithin() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Копирует последовательность элементов массива внутри массива.
Array.prototype.fill() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Заполняет все элементы массива от начального индекса до конечного индекса указанным значением.
Array.prototype.pop()
Удаляет последний элемент из массива и возвращает его.
Array.prototype.push()
Добавляет один или более элементов в конец массива и возвращает новую длину массива.
Array.prototype.reverse()
Переворачивает порядок элементов в массиве — первый элемент становится последним, а последний — первым.
Array.prototype.shift()
Удаляет первый элемент из массива и возвращает его.
Array.prototype.sort()
Сортирует элементы массива на месте и возвращает отсортированный массив.
Array.prototype.splice()
Добавляет и/или удаляет элементы из массива.
Array.prototype.unshift()
Добавляет один или более элементов в начало массива и возвращает новую длину массива.

Методы доступа

Эти методы не изменяют массив, а просто возвращают его в ином представлении.

Array.prototype.concat()
Возвращает новый массив, состоящий из данного массива, соединённого с другим массивом и/или значением (списком массивов/значений).
Array.prototype.includes() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Определяет, содержится ли в массиве указанный элемент, возвращая, соответственно, true или false.
Array.prototype.join()
Объединяет все элементы массива в строку.
Array.prototype.slice()
Извлекает диапазон значений и возвращает его в виде нового массива.
Array.prototype.toSource() Это API не было стандартизировано.
Возвращает литеральное представление указанного массива; вы можете использовать это значение для создания нового массива. Переопределяет метод Object.prototype.toSource().
Array.prototype.toString()
Возвращает строковое представление массива и его элементов. Переопределяет метод Object.prototype.toString().
Array.prototype.toLocaleString()
Возвращает локализованное строковое представление массива и его элементов. Переопределяет метод Object.prototype.toLocaleString().
Array.prototype.indexOf()
Возвращает первый (наименьший) индекс элемента внутри массива, равный указанному значению; или -1, если значение не найдено.
Array.prototype.lastIndexOf()
Возвращает последний (наибольший) индекс элемента внутри массива, равный указанному значению; или -1, если значение не найдено.

Методы обхода

Некоторые методы принимают в качестве аргументов функции, вызываемые при обработке массива. Когда вызываются эти методы, достаётся длина массива, и любой элемент, добавленный свыше этой длины изнутри функции обратного вызова не посещается. Другие изменения в массиве (установка значения или удаление элемента) могут повлиять на результаты операции, если изменённый элемент метод посещает после изменения. Хотя специфическое поведение этих методов в таких случаях хорошо определено, вы не должны на него полагаться, чтобы не запутывать других людей, читающих ваш код. Если вам нужно изменить массив, лучше вместо этого скопируйте его в новый массив.

Array.prototype.forEach()
Вызывает функцию для каждого элемента в массиве.
Array.prototype.entries() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает новый объект итератора массива Array Iterator, содержащий пары ключ / значение для каждого индекса в массиве.
Array.prototype.every()
Возвращает true, если каждый элемент в массиве удовлетворяет условию проверяющей функции.
Array.prototype.some()
Возвращает true, если хотя бы один элемент в массиве удовлетворяет условию проверяющей функции.
Array.prototype.filter()
Создаёт новый массив со всеми элементами этого массива, для которых функция фильтрации возвращает true.
Array.prototype.find() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает искомое значение в массиве, если элемент в массиве удовлетворяет условию проверяющей функции или undefined, если такое значение не найдено.
Array.prototype.findIndex() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает искомый индекс в массиве, если элемент в массиве удовлетворяет условию проверяющей функции или -1, если такое значение не найдено.
Array.prototype.keys() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает новый итератор массива, содержащий ключи каждого индекса в массиве.
Array.prototype.map()
Создаёт новый массив с результатами вызова указанной функции на каждом элементе данного массива.
Array.prototype.reduce()
Применяет функцию к аккумулятору и каждому значению массива (слева-направо), сводя его к одному значению.
Array.prototype.reduceRight()
Применяет функцию к аккумулятору и каждому значению массива (справа-налево), сводя его к одному значению.
Array.prototype.values() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает новый объект итератора массива Array Iterator, содержащий значения для каждого индекса в массиве.
Array.prototype[@@iterator]() Это экспериментальное API, которое не должно использоваться в рабочем коде.
Возвращает новый объект итератора массива Array Iterator, содержащий значения для каждого индекса в массиве.

Общие методы массива

Иногда хочется применить методы массива к строкам или другим массивоподобным объектам (например, к аргументам функции). Делая это, вы трактуете строку как массив символов (другими словами, рассматриваете не-массив в качестве массива). Например, в порядке проверки каждого символа в переменной str на то, что он является буквой (латинского алфавита), вы пишете следущий код:

function isLetter(character) {
  return character >= 'a' && character <= 'z';
}

if (Array.prototype.every.call(str, isLetter)) {
  console.log("Строка '" + str + "' содержит только (латинские) буквы!");
}

Эта запись довольно расточительна и в JavaScript 1.6 введён общий сокращённый вид:

if (Array.every(str, isLetter)) {
  console.log("Строка '" + str + "' содержит только (латинские) буквы!");
}

Общие методы также доступны для объекта String.

В настоящее время они не являются частью стандартов ECMAScript (хотя в ES2015 для достижения поставленной цели можно использовать Array.from()). Следующая прослойка позволяет использовать их во всех браузерах:

// Предполагаем, что дополнения массива уже присутствуют (для них так же можно использовать polyfill'ы)
(function() {
  'use strict';

  var i,
    // Мы могли построить массив методов следующим образом, однако метод
    //  getOwnPropertyNames() нельзя реализовать на JavaScript:
    // Object.getOwnPropertyNames(Array).filter(function(methodName) {
    //   return typeof Array[methodName] === 'function'
    // });
    methods = [
      'join', 'reverse', 'sort', 'push', 'pop', 'shift', 'unshift',
      'splice', 'concat', 'slice', 'indexOf', 'lastIndexOf',
      'forEach', 'map', 'reduce', 'reduceRight', 'filter',
      'some', 'every'
    ],
    methodCount = methods.length,
    assignArrayGeneric = function(methodName) {
      if (!Array[methodName]) {
        var method = Array.prototype[methodName];
        if (typeof method === 'function') {
          Array[methodName] = function() {
            return method.call.apply(method, arguments);
          };
        }
      }
    };

  for (i = 0; i < methodCount; i++) {
    assignArrayGeneric(methods[i]);
  }
}());

Примеры

Пример: создание массива

Следующий пример создаёт массив msgArray с длиной 0, присваивает значения элементам msgArray[0] и msgArray[99], что изменяет длину массива на 100.

var msgArray = [];
msgArray[0] = 'Привет';
msgArray[99] = 'мир';

if (msgArray.length === 100) {
  console.log('Длина равна 100.');
}

Пример: создание двумерного массива

Следующий код создаёт шахматную доску в виде двумерного массива строк. Затем он перемещает пешку путём копирования символа 'p' в позиции (6,4) на позицию (4,4). Старая позиция (6,4) затирается пустым местом.

var board = [
  ['R','N','B','Q','K','B','N','R'],
  ['P','P','P','P','P','P','P','P'],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  ['p','p','p','p','p','p','p','p'],
  ['r','n','b','q','k','b','n','r'] ];

console.log(board.join('\n') + '\n\n');

// Двигаем королевскую пешку вперёд на две клетки
board[4][4] = board[6][4];
board[6][4] = ' ';
console.log(board.join('\n'));

Ниже показан вывод:

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
p,p,p,p,p,p,p,p
r,n,b,q,k,b,n,r

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , ,p, , ,
 , , , , , , ,
p,p,p,p, ,p,p,p
r,n,b,q,k,b,n,r

Спецификации

Спецификация Статус Комментарий
ECMAScript 1-е издание. Стандарт Изначальное определение.
ECMAScript 5.1 (ECMA-262)
Определение 'Array' в этой спецификации.
Стандарт Добавлены новые методы: Array.isArray, indexOf, lastIndexOf, every, some, forEach, map, filter, reduce, reduceRight.
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'Array' в этой спецификации.
Стандарт Добавлены новые методы: Array.from, Array.of, find, findIndex, fill, copyWithin.
ECMAScript 2016 (ECMA-262)
Определение 'Array' в этой спецификации.
Стандарт Добавлен новый метод: Array.prototype.includes()

Поддержка браузерами

BCD tables only load in the browser

 

Смотрите также