Javascript массивы

8789

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

Создаем Массив js

var fruits = ['Apple', 'Banana'];

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

Как получить доступ (индекс) к элементу Массива?

var first = fruits[0];
// Apple

var last = fruits[fruits.length - 1];
// Banana

Цикл по Массиву

fruits.forEach(function(item, index, array) {
  console.log(item, index);
});
// Apple 0
// Banana 1

Добавление в конец Массива

var newLength = fruits.push('Orange');
// ["Apple", "Banana", "Orange"]

Удаление из конца Массива

var last = fruits.pop(); // удаление Orange (из конца)
// ["Apple", "Banana"];

Удаление из начала Массива

var first = fruits.shift(); // удаление Apple из начала
// ["Banana"];

Добавление в начало Массива

var newLength = fruits.unshift('Strawberry') // добавляет в начало
// ["Strawberry", "Banana"];

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

fruits.push('Mango');
// ["Strawberry", "Banana", "Mango"]

var pos = fruits.indexOf('Banana');
// 1

Удаление элемента по номеру позиции

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

Удаление элементов из номера позиции

var vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot'];
console.log(vegetables); 
// ["Cabbage", "Turnip", "Radish", "Carrot"]

var pos = 1, n = 2;

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

console.log(vegetables); 
// ["Cabbage", "Carrot"] (заданный массив изменён)

console.log(removedItems); 
// ["Turnip", "Radish"]

Копия Массива

var shallowCopy = fruits.slice(); // это как скопировать
// ["Strawberry"]

Синтаксис в Java script

[element0, element1, ..., elementN]
new Array(element0, element1[, ...[, elementN]])
new Array(arrayLength)

elementN Массив в JavaScript инициализируется с помощью переданных элементов, за исключением случая, когда в конструктор Array передаётся один аргумент и этот аргумент является числом (см. ниже). Стоит обратить внимание, что этот особый случай применяется только к JavaScript-массивам, создаваемым с помощью конструктора Array, а не к литеральным массивам, создаваемым с использованием скобочного синтаксиса.

arrayLength Если конструктору Array передаётся единственный аргумент, являющийся целым числом в диапазоне от 0 до 232-1 (включительно), будет возвращён новый пустой JavaScript-массив, длина которого установится в это число. Если аргументом будет любое другое число, возникнет исключение RangeError.

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

Массивы в 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 взаимосвязано с числовыми свойствами. Некоторые встроенные методы массива (например, joinsliceindexOf и т.д.) учитывают значение свойства length при своём вызове. Другие методы (например, pushsplice и т.д.) в результате своей работы также обновляют свойство 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.execString.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() 
Создаёт новый экземпляр Array из массивоподобного или итерируемого объекта.
Array.isArray()
Возвращает true, если значение является массивом, иначе возвращает false.
Array.observe() 
Асинхронно наблюдает за изменениями в массиве, подобно методу Object.observe() для объектов. Метод предоставляет поток изменений в порядке их возникновения.
Array.of() 
Создаёт новый экземпляр Array с переменным количеством аргументов, независимо от числа или типа аргументов.

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

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

Свойства

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

Array.prototype.lengthОтражает количество элементов в массиве.

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

Array.prototype.copyWithin() 
Копирует последовательность элементов массива внутри массива.
Array.prototype.fill() 
Заполняет все элементы массива от начального индекса до конечного индекса указанным значением.
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() 
Определяет, содержится ли в массиве указанный элемент, возвращая, соответственно, true или false.
Array.prototype.join()
Объединяет все элементы массива в строку.
Array.prototype.slice()
Извлекает диапазон значений и возвращает его в виде нового массива.
Array.prototype.toSource() 
Возвращает литеральное представление указанного массива; вы можете использовать это значение для создания нового массива. Переопределяет метод 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() Возвращает новый объект итератора массива Array Iterator, содержащий пары ключ / значение для каждого индекса в массиве.Array.prototype.every()Возвращает true, если каждый элемент в массиве удовлетворяет условию проверяющей функции.Array.prototype.some()Возвращает true, если хотя бы один элемент в массиве удовлетворяет условию проверяющей функции.Array.prototype.filter()Создаёт новый массив со всеми элементами этого массива, для которых функция фильтрации возвращает true.Array.prototype.find() Возвращает искомое значение в массиве, если элемент в массиве удовлетворяет условию проверяющей функции или undefined, если такое значение не найдено.Array.prototype.findIndex() Возвращает искомый индекс в массиве, если элемент в массиве удовлетворяет условию проверяющей функции или -1, если такое значение не найдено.Array.prototype.keys() Возвращает новый итератор массива, содержащий ключи каждого индекса в массиве.Array.prototype.map()Создаёт новый массив с результатами вызова указанной функции на каждом элементе данного массива.Array.prototype.reduce()Применяет функцию к аккумулятору и каждому значению массива (слева-направо), сводя его к одному значению.Array.prototype.reduceRight()Применяет функцию к аккумулятору и каждому значению массива (справа-налево), сводя его к одному значению.Array.prototype.values() Возвращает новый объект итератора массива Array Iterator, содержащий значения для каждого индекса в массиве.Array.prototype[@@iterator]() Возвращает новый объект итератора массива Array Iterator, содержащий значения для каждого индекса в массиве.

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

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]);
  }
}());

Примеры на JS

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

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

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

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

Следующий код создаёт шахматную доску в виде двумерного массива строк. Затем он перемещает пешку путём копирования символа ‘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