Массивы — один из фундаментальных аспектов JavaScript, и их легко освоить. В этой статье мы рассмотрим все необходимое, что нужно знать о массивах в JavaScript.

Массив — это объект в JavaScript, который используется для хранения списка значений, разделенных запятыми, в квадратных скобках. let array = ["string", 20, false]. Значения в массиве называются «элементами», и каждый элемент в массиве имеет числовую позицию, известную как его «индекс». Значение индекса находится в диапазоне от 0 (первый элемент массива) до 4 294 967 295.

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

Самый простой способ создать массив — использовать литерал массива let array = []. При создании массива нет необходимости указывать количество элементов, которые должны содержаться в массиве, поскольку они носят динамический характер и могут содержать элементы разных типов данных. Массивы также могут содержать в качестве элементов произвольные выражения и литералы объектов.

let size = "medium";
let carObject = {
  name: "Tesla",
  model: "S8"
}
''' An array containing arbitrary expressions and object literals'''
let arrayItems = [30, size, "Pizza", carObject, {x:1.3, y:4.4}]

Конструктор Array()

Конструктор Array() — это еще один способ создания массивов, и его можно использовать тремя разными способами:

  1. Вызов без аргумента let array = new Array(); // creates an empty array same as array = []
  2. Вызов с одним числовым аргументом, указывающим длину массива let array = new Array(10);
  3. Явно укажите два или более элемента массива или один нечисловой элемент для массива
let array = new Array(10, "Hello", "Mayor", "Texas", 23, 09);
let arr = new Array("states");  //arr = ["states"]

Функция Array.of()

Когда конструктор Array() вызывается с одним числовым аргументом, он использует этот аргумент как длину массива. Функция Array.of() решает эту проблему. Функция Array.of() создаст и вернет новый массив, используя значения его аргументов в качестве элементов массива, независимо от того, сколько их.

let array = Array.of(10);   // same as let array = [10];

Функция Array.from()

Array.from() — это метод создания настоящей копии массива, подобного объекту. В качестве первого аргумента он принимает итерируемый или подобный массиву объект, а в качестве необязательного второго аргумента — функцию.

let array = ["cars", "dogs", "cats"];
let arrayCopy = Array.from(array); // gives ["cars", "dogs", "cats"]
Array.from("STRING");  // ['S', 'T', 'R', 'I', 'N', 'G']

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

let evenNum = [2, 4, 6, 8, 10];
let evenSquare = Array.from(evenNum, element => element*element);
// [4, 16, 36, 64, 100]

Чтение и запись элементов в массив JavaScript

Оператор [] используется для доступа к элементам массива.

let array = ["cars", "dogs", "cats"];
let vehicle = array[0];  // read the first element in the array
array[3]=false;  // write to array ["cars", "dogs", "cats", false]

Когда вы пытаетесь прочитать значение несуществующего индекса, вы получаете undefined в качестве возвращаемого значения. Хотя вы можете записать любое значение индекса в допустимом диапазоне массива (0 — 4 294 967 295).

Разреженные массивы

Разреженный массив — это массив, элементы которого не имеют смежных индексов. Обычно длина массива должна указывать количество элементов в массиве, но в разреженном массиве длина массива будет больше, чем количество элементов в массиве.

let array = ["cars", "dogs", "cats"];
array[5] = false; // ["cars", "dogs", "cats",,,false] 
''' array.length will give a value 6 '''

Оператор спреда

Оператор расширения «» может использоваться для включения элементов одного массива в литерал массива. Это также способ создать копию массива.

let odd= [9, 5, 3, 7];
let numbers = [ 4, ...odd, 3]; // [4, 9, 5, 3, 7, 3]

Оператор распространения также работает для итерируемых объектов, таких как строки.

let alphabets = [..."Elon"]; // ["E", "L", "O", "N"]

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

Самый простой способ добавить элементы в массив — присвоить элементам новые индексы.

let class = ["small", "medium"];
class[2]="big";  // ["small", "medium", "big"]

Метод push также можно использовать для добавления одного или нескольких элементов в конец массива. class.push("enormous", "colossal");. Чтобы добавить элементы в начало массива, используйте метод unshift(), который работает так же, как push, но добавляет элементы в начало массива.

Метод pop() противоположен push(), он удаляет последний элемент массива. Метод shift() противоположен unshift(), он удаляет первый элемент массива. Использование методов push(), pop(), unshift() и shift() соответственно корректирует индексы элементов в массиве.

Оператор delete также используется для удаления элементов в массиве, но он присваивает удаляемому элементу значение undefined и не корректирует соответствующим образом индексы элементов в массиве, тем самым делая массив разреженным.

let names = ["Abel", "Benny", "Clive", "David"];
delete names[2]
// names ["Abel", "Benny", , "David"]

Многомерные массивы

Хотя JavaScript не поддерживает настоящие многомерные массивы, вы можете создать их, используя массивы массивов. Чтобы получить доступ к элементу в массиве массивов, просто используйте оператор [] в соответствии с размерностью массива.

let matrix = [
  [0, 1], [2, 3], [4, 5]
];
matrix[2][0] // 4

Методы массива JavaScript

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

1. Методы итератора массива

Методы итератора массива предназначены для перебора массива путем передачи каждого элемента массива в функцию без изменения исходного массива, для которого они вызываются. Эти методы принимают функцию в качестве первого аргумента и вызывают эту функцию для каждого элемента массива. Когда функция вызывается для элементов массива, она может получить доступ к значению элемента массива, индексу элемента и самому массиву.

Метод forEach(). Этот метод многократно вызывает каждый элемент массива и вызывает свою функцию для каждого элемента массива.

let data = [1, 2, 3, 4, 5];
// compute the sum of values in the array
data.forEach(value => sum += value );    // sum = 15
// multiply each element in the array by its index
data.forEach( (value, index, array) => {
  array[index] = value * index;
});    // [0, 2, 6, 12, 20]

Метод map().Метод map() работает аналогично методу forEach(), разница в том, что map() будет работать с каждым элементом в array и вернуть новый массив по умолчанию без изменения исходного массива.

let data = [1, 2, 3, 4, 5];
data.map( v => v*v );    // [1, 4, 9, 16, 25]

Метод filter(). Этот метод использует функцию-предикат; функция, которая возвращает true или false, и функция вызывается точно так же, как функции map() и forEach(). filter() возвращает массив, содержащий подмножество элементов массива, для которого он вызывается. Если значение оценивается как истинное или удовлетворяет определенному условию, элемент становится частью подмножества.

let data = [1, 2, 3, 4, 5];
data.filter( x => x<3);   // [1, 2] (values less than)
sparse.filter( () => true );  //remove undefined and null elements

Метод find() и findIndex(): этот метод аналогичен методу filter, они будут перебирать элементы в массиве в поисках элемента, который возвращает значение true. В отличие от filter(), find() и findIndex() прекращают итерацию, как только находят элемент. Если элемент не найден, find() возвращает undefined, а findIndex() возвращает -1.

Методы every() и some(). Эти методы применяют функцию-предикат, указанную вами, к элементам массива, а затем возвращают значение true или false. Метод every() возвращает значение true, если функция предиката возвращает значение true для всех элементов массива.

let data = [1, 2, 3, 4, 5];
data.every( val => val%2===0 );  //false: not all values are even

Метод some() возвращает значение true, если в массиве существует хотя бы один элемент, для которого предикат возвращает значение true.

let data = [1, 2, 3, 4, 5];
data.some(val => val%2===0);  //true: some values are true
data.some(isNaN);            // false: all values are numbers

every() и some() прекратят повторение, как только будет известно возвращаемое значение.

Методыreduce() и reduceRight(). Эти методы выполняют операцию сокращения массива для получения одного значения. reduce() принимает два аргумента: первый представляет собой функцию, которая выполняет операцию сокращения путем объединения или сведения двух значений к одному, а второй необязательный аргумент становится начальным значением, передаваемым функции. reduceRight() работает аналогично reduce(), за исключением того, что он обрабатывает массив от самого высокого индекса к самому низкому индексу (справа налево);

let data = [1, 2, 3, 4, 5];
data.reduce( (x,y)=> x+y, 0 );    // returns 15
data.reduceRight( (x,y)=> x*y);    // returns 120
data.reduce( (x,y)=> (x>y)? x:y);    // returns 5

2. Сведение массивов с помощью методов flat() и flatMap()

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

[1, [2, 3]].flat();  // [1, 2, 3]
let data = [1, [2, [3, [4]]]];
data.flat(2);  // returns [1, 2, 3, [4]]
data.flat(3);  // returns [1, 2, 3, 4]
data.flat(5);  // returns [1, 2, 3, 4]

flatMap() работает так же, как map(), за исключением того, что возвращаемый массив передается методу flat(). Так же, как array.map(function).flat().

let sentence = ["JavaScript", "is a programming", "language"];
sentence.flatMap(value => value.split(" ")); 
  // ['JavaScript', 'is', 'a', 'programming', 'language']

3. Добавление массивов с помощью метода concat()

Метод concat() создает и возвращает новый массив, содержащий элементы массива, для которого вызывается метод concat(), за которыми следуют аргументы concat() без изменения исходного массива. Если аргументы являются массивами, они выравниваются только на один уровень, а не рекурсивно.

[1, 2, 3, 4].concat([5, 6, 7]);  //return: [1, 2, 3, 4, 5, 6, 7]
[1, 2, 3].concat(4, 5);   //return: [1, 2, 3, 4, 5]
[1, 2, 3].concat([4, 5],[6, 7]);  // return [1, 2, 3, 4, 5, 6, 7]
[1, 2, 3].concat(4, [5,[6, 7]]);  // return [1, 2, 3, 4, 5, [6, 7]]

4. Стеки и очереди с push(), pop(), shift() и unshift()

Хотя мы рассмотрели эти методы ранее в статье, мы рассмотрим их еще раз.

Методы push() и pop() работают с массивами так, как если бы они были стеками, они используют подход «первым пришел последним» (FIFO). push() добавляет один или несколько элементов в конец массива, а pop() удаляет последний элемент массива.

let colors = ["red", "blue", "green"];
colors.push("White", "Charlie");  // ["red", "blue", "green", "White", "Charlie"]
colors.pop(); //["red", "blue", "green", "White"]

При использовании массива в качестве аргумента метода push() push не сглаживает массив, который вы ему передаете. Вместо этого вы можете использовать оператор спреда, чтобы явно сгладить его. colors.push(...values);

unshift() и shift() ведут себя так же, как методы push() и pop(), за исключением того, что они вставляют и удаляют элементы из начала массива.

let radio = ['Charlie', 'Delta'];
radio.unshift('Alpha', 'Beta');  //['Alpha', 'Beta', 'Charlie', 'Delta']
radio.shift(); //['Beta', 'Charlie', 'Delta']

5. Подмассивы с методами slice(), splice(), fill() и copywithin()

Метод slice(). Как следует из названия, метод slice вырезает элементы массива без изменения исходного массива. Он возвращает копию раздела массива от начального аргумента до конечного аргумента (не включительно). Отрицательный индекс может использоваться для обозначения смещения от конца массива. Например, -2 относится к предпоследнему элементу массива.

let data = [1, 2, 3, 4, 5];
data.slice(1,3);   //[2,3];
data.slice(1, -1);  // [2,3,4];
data.slice(3);      // [4,5];

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

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

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
numbers.splice(5);  //return: [6, 7, 8, 9], numbers = [1, 2, 3, 4, 5]
numbers.splice(1,3); // return: [2, 3, 4], numbers = [1,5]

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

let numbers = [1,2,3];
numbers.splice(1,0,['a','b']); // []; numbers = // [1,['a','b'],2,3]

Метод fill()(): этот метод устанавливает для элементов массива заданное значение. Он изменяет массив, к которому он вызывается. Его первый аргумент — это значение для установки элемента массива, а второй необязательный аргумент указывает начальный индекс и необязательный третий аргумент, определяющий конечный индекс. Если второй и третий не включены, массив будет заполнен от начала до конца.

let data = new Array(6);
data.fill(2);  // [2,2,2,2,2,2];
data.fill(5,3); // [2,2,2,3,3,3];

Метод copyWithin(). Этот метод копирует фрагмент массива в новую позицию внутри массива и изменяет массив, но не изменяет длину массива. Первый аргумент — это начальная позиция индекса, в которую будет помещен копируемый элемент, а второй аргумент — это индекс первого копируемого элемента, и если он опущен, используется 0. Третий аргумент — это индекс последнего элемента, который нужно разрезать или скопировать, и, если он опущен, используется длина массива.

let numbers = [1, 2, 3, 4, 5];
numbers.copyWithin(0,3,5);  // [4, 5, 3, 4, 5]

6. Методы поиска и сортировки массива

Методы indexOf() и lastIndexOf(). Эти методы будут искать в элементах массива указанное значение и возвращать индекс первого найденного совпадения или -1, если такое значение не найдено. indexOf() ищет массив от начала до конца, а lastIndexOf() ищет от конца к началу.

const names = ["Angel", "Barry", "Collins", "Daniel", "Barry"];
names.indexOf("Collins");   // 2
names.lastIndexOf("Barry");   // 4

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

Метод include(). Этот метод принимает один аргумент и возвращает либо true, либо false, если массив содержит этот аргумент. Метод includes() отличается от indexOf() тем, что он может обнаруживать NaN в массиве, а indexOf() — нет.

let obj = [1, true, "3", NaN];
obj.includes(1);  // true
obj.includes(NaN);  // true
obj.indexOf(NaN);  // -1

Метод sort(): метод sort сортирует элементы в массиве на месте и возвращает отсортированный массив, а если массив содержит неопределенное, он сортируется до конца массива.

let a = ["banana", "cherry", "apple", 90, 19];
a.sort(); // [19, 90, 'apple', 'banana', 'cherry']
let a = [33, 4, 1111, 222];
a.sort();  // a == [1111, 222, 33, 4]; alphabetical order
a.sort(function(a,b) {  // Pass a comparator function
  return a-b;         // Returns < 0, 0, or > 0, depending on order
});   // a == [4, 33, 222, 1111]; numerical order
a.sort((a,b) => b-a);  // a == [1111, 222, 33, 4]; reverse numerical order
let a = ["ant", "Bug", "cat", "Dog"]; 
a.sort();    // a == ["Bug","Dog","ant","cat"]; case-sensitive sort
a.sort(function(s,t) {    
  let a = s.toLowerCase();    
  let b = t.toLowerCase();    
  if (a < b) return -1;    
  if (a > b) return 1;    
  return 0; 
});   // a == ["ant","Bug","cat","Dog"]; case-insensitive sort

Метод reverse(). Этот метод меняет порядок элементов в массиве на обратный.

let a = [1, 2, 3, 4];
a.reverse();  // a==[4, 3, 2, 1]

7. Преобразование массива в строку

Примечание. Если вы хотите сохранить содержимое массива в текстовом виде для последующего повторного использования, сериализуйте массив с помощью JSON.stringify().

Метод join() возвращает строку, преобразуя все элементы массива в строку и объединяя их. Можно указать необязательную строку для разделения элементов в возвращаемой строке, и если разделитель не используется, по умолчанию используется запятая ,.

let data = [1, 2, 3, 5, 9];
data.join();  // "1,2,3,5,9"
data.join("");  //"12359"
data.join(" ");  //"1 2 3 5 9"

Метод Array.join() является обратным методу String.split().

Для справки прочтите Полное руководство по JavaScript, 7-е издание Дэвида Фланагана. Эта статья написана в соответствии с Полным руководством по JavaScript.