Spec-Zone.ru › JavaScript

Массив

Базовый уровень Широко доступно

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

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

Описание

В JavaScript массивы не являются примитивами, а представляют собой Array объекты со следующими основными характеристиками:

  • Массивы JavaScript изменяемы по размеру и могут содержать смесь различных типов данных. (Если эти характеристики нежелательны, используйте типизированные массивы.)
  • Массивы JavaScript не являются ассоциативными массивами, поэтому элементы массива нельзя получить, используя произвольные строки в качестве индексов; доступ должен осуществляться с использованием неотрицательных целых чисел (или их строковой формы) в качестве индексов.
  • Массивы JavaScript имеют нулевую индексацию: первый элемент массива находится по индексу 0, второй — по индексу 1 и так далее — последний элемент равен значению свойства length массива минус 1.
  • Операции копирования массива в JavaScript создают поверхностные копии. (Все стандартные встроенные операции копирования с *любыми* объектами JavaScript создают поверхностные копии, а не глубокие копии).

Индексы массивов

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

Элементы массива — это свойства объекта, так же как toString является свойством (точнее, toString() — это метод). Тем не менее, попытка получить доступ к элементу массива следующим образом вызовет ошибку синтаксиса, потому что имя свойства недопустимо:

arr.0; // a syntax error

Синтаксис JavaScript требует, чтобы свойства, начинающиеся с цифры, получались с использованием скобочной нотации вместо точечной нотации. Также возможно заключить индексы массива в кавычки (например, years['2'] вместо years[2]), хотя обычно это не требуется.

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

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

Только years['2'] является фактическим индексом массива. years['02'] — это произвольное строковое свойство, которое не будет обрабатываться при итерации массива.

Связь между length и числовыми свойствами

Свойство length массива JavaScript и числовые свойства связаны.

Несколько встроенных методов массива (например, join(), slice(), indexOf() и т. д.) учитывают значение свойства length массива при их вызове.

Другие методы (например, push(), splice() и т. д.) также приводят к обновлению свойства length массива.

const fruits = [];
fruits.push("banana", "apple", "peach");
console.log(fruits.length); // 3

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

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

Увеличение length расширяет массив, добавляя пустые слоты без создания каких-либо новых элементов — даже undefined.

fruits.length = 10;
console.log(fruits); // ['banana', 'apple', 'peach', empty x 2, 'mango', empty x 4]
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 10
console.log(fruits[8]); // undefined

Однако уменьшение свойства length удаляет элементы.

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

Это подробнее объясняется на странице length.

Методы массива и пустые слоты

Методы массива ведут себя по-разному при встрече с пустыми слотами в разреженных массивах. В целом, старые методы (например, forEach) обрабатывают пустые слоты иначе, чем индексы, содержащие undefined.

Методы, которые имеют специальное отношение к пустым слотам, включают в себя: concat(), copyWithin(), every(), filter(), flat(), flatMap(), forEach(), indexOf(), lastIndexOf(), map(), reduce(), reduceRight(), reverse(), slice(), some(), sort() и splice(). Методы итерации, такие как forEach, вообще не посещают пустые слоты. Другие методы, такие как concat, copyWithin и т. д., сохраняют пустые слоты при копировании, так что в итоге массив остается разреженным.

const colors = ["red", "yellow", "blue"];
colors[5] = "purple";
colors.forEach((item, index) => {
  console.log(`${index}: ${item}`);
});
// Output:
// 0: red
// 1: yellow
// 2: blue
// 5: purple

colors.reverse(); // ['purple', empty × 2, 'blue', 'yellow', 'red']

Более новые методы (например, keys) не обрабатывают пустые слоты специально и относятся к ним так, как будто они содержат undefined. Методы, которые объединяют пустые слоты с undefined элементами, включают в себя: entries(), fill(), find(), findIndex(), findLast(), findLastIndex(), includes(), join(), keys(), toLocaleString(), toReversed(), toSorted(), toSpliced(), values() и with().

const colors = ["red", "yellow", "blue"];
colors[5] = "purple";
const iterator = colors.keys();
for (const key of iterator) {
  console.log(`${key}: ${colors[key]}`);
}
// Output
// 0: red
// 1: yellow
// 2: blue
// 3: undefined
// 4: undefined
// 5: purple

const newColors = colors.toReversed(); // ['purple', undefined, undefined, 'blue', 'yellow', 'red']

Копирующие методы и мутирующие методы

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

  • Объекты: ссылка на объект копируется в новый массив. Как исходный, так и новый массив ссылаются на один и тот же объект. То есть, если изменяется объект, на который есть ссылка, изменения будут видны как в новом, так и в исходном массивах.
  • Примитивные типы, такие как строки, числа и булевы значения (не String, Number и объекты Boolean): их значения копируются в новый массив.

Другие методы изменяют массив, на котором был вызван метод, в этом случае возвращаемое значение отличается в зависимости от метода: иногда ссылка на тот же массив, иногда длина нового массива.

Следующие методы создают новые массивы, обращаясь к this.constructor[Symbol.species] для определения конструктора, который следует использовать: concat(), filter(), flat(), flatMap(), map(), slice() и splice() (для создания массива удаленных элементов, который возвращается).

Следующие методы всегда создают новые массивы с использованием базового конструктора Array: toReversed(), toSorted(), toSpliced() и with().

Следующая таблица перечисляет методы, которые изменяют исходный массив, и соответствующие им неизменяемые альтернативы:

Изменяющий метод Неизменяемая альтернатива
copyWithin() Нет однометодовой альтернативы
fill() Нет однометодовой альтернативы
pop() slice(0, -1)
push(v1, v2) concat([v1, v2])
reverse() toReversed()
shift() slice(1)
sort() toSorted()
splice() toSpliced()
unshift(v1, v2) toSpliced(0, 0, v1, v2)

Простой способ превратить изменяющий метод в неизменяемую альтернативу — использовать синтаксис распространения или slice() для предварительного создания копии:

arr.copyWithin(0, 1, 2); // mutates arr
const arr2 = arr.slice().copyWithin(0, 1, 2); // does not mutate arr
const arr3 = [...arr].copyWithin(0, 1, 2); // does not mutate arr

Итеративные методы

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

method(callbackFn, thisArg)

Где callbackFn принимает три аргумента:

element
Текущий обрабатываемый элемент в массиве.
index
Индекс текущего обрабатываемого элемента в массиве.
array
Массив, на котором был вызван метод.

Что callbackFn должен вернуть, зависит от вызванного метода массива.

Аргумент thisArg (по умолчанию undefined) будет использоваться в качестве значения this при вызове callbackFn. Значение this, которое в конечном итоге будет наблюдаться callbackFn, определяется в соответствии с обычными правилами: если callbackFn является нестрогим, примитивные значения this оборачиваются в объекты, а undefined/null заменяется на globalThis. Аргумент thisArg не имеет значения для любого callbackFn, определенного с помощью стрелочной функции, поскольку стрелочные функции не имеют собственного this привязки.

Аргумент array, передаваемый в callbackFn, наиболее полезен, если вы хотите прочитать другой индекс во время итерации, потому что у вас не всегда может быть существующая переменная, ссылающаяся на текущий массив. Вам следует избегать изменения массива во время итерации (см. изменение исходного массива в итеративных методах), но вы также можете использовать этот аргумент для этого. Аргумент array — это *не* массив, который строится, в случае таких методов, как map(), filter() и flatMap() — нет способа получить доступ к строящемуся массиву из функции обратного вызова.

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

Следующие методы являются итеративными: every(), filter(), find(), findIndex(), findLast(), findLastIndex(), flatMap(), forEach(), map() и some().

В частности, every(), find(), findIndex(), findLast(), findLastIndex() и some() не всегда вызывают callbackFn для каждого элемента — они останавливают итерацию, как только определяется возвращаемое значение.

Методы reduce() и reduceRight() также принимают функцию обратного вызова и запускают ее максимум один раз для каждого элемента массива, но имеют немного отличающиеся сигнатуры от типичных итеративных методов (например, они не принимают thisArg).

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

Итеративные методы обходят массив следующим образом (с опущенными множеством технических деталей):

function method(callbackFn, thisArg) {
  const length = this.length;
  for (let i = 0; i < length; i++) {
    if (i in this) {
      const result = callbackFn.call(thisArg, this[i], i, this);
      // Do something with result; maybe return early
    }
  }
}

Обратите внимание на следующее:

  1. Не все методы выполняют проверку i in this. Методы find, findIndex, findLast и findLastIndex ее не выполняют, но другие методы выполняют.
  2. length запоминается перед началом цикла. Это влияет на обработку вставок и удалений во время итерации (см. изменение исходного массива в итеративных методах).
  3. Метод не запоминает содержимое массива, поэтому, если какой-либо индекс изменяется во время итерации, новое значение может быть обнаружено.
  4. Приведенный выше код обходит массив в порядке возрастания индексов. Некоторые методы обходят в порядке убывания индексов (for (let i = length - 1; i >= 0; i--)): reduceRight(), findLast() и findLastIndex().
  5. reduce и reduceRight имеют немного отличающиеся сигнатуры и не всегда начинаются с первого/последнего элемента.

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

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

const arrayLike = {
  0: "a",
  1: "b",
  length: 2,
};
console.log(Array.prototype.join.call(arrayLike, "+")); // 'a+b'

Нормализация свойства length

Свойство length преобразуется в целое число, а затем ограничивается диапазоном от 0 до 253 - 1. NaN становится 0, поэтому даже когда length отсутствует или является undefined, он ведет себя так, как если бы имел значение 0.

Язык избегает установки length в небезопасное целое число. Все встроенные методы вызовут TypeError, если length будет установлено в число большее, чем 253 - 1. Однако, поскольку свойство length массивов вызывает ошибку, если оно установлено больше, чем 232 - 1, предел безопасного целого числа обычно не достигается, если только метод не вызывается для не-массивного объекта.

Array.prototype.flat.call({}); // []

Некоторые методы массива устанавливают свойство length объекта массива. Они всегда устанавливают значение после нормализации, поэтому length всегда становится целым числом.

const a = { length: 0.7 };
Array.prototype.push.call(a);
console.log(a.length); // 0

Объекты, похожие на массивы

Термин объект, похожий на массив относится к любому объекту, который не вызывает ошибку во время процесса length преобразования, описанного выше. На практике ожидается, что такой объект действительно будет иметь свойство length и индексированные элементы в диапазоне 0 до length - 1. (Если он не имеет всех индексов, он будет функционально эквивалентен разреженному массиву.) Любой целый индекс меньше нуля или больше length - 1 игнорируется, когда метод массива работает с объектом, похожим на массив.

Многие объекты DOM похожи на массивы — например, NodeList и HTMLCollection. Объект arguments также похож на массив. Вы можете вызывать методы массива для них, даже если у них самих нет этих методов.

function f() {
  console.log(Array.prototype.join.call(arguments, "+"));
}

f("a", "b"); // 'a+b'

Конструктор

Array()
Создает новый объект Array.

Статические свойства

Array[Symbol.species]
Возвращает конструктор Array.

Статические методы

Array.from()
Создает новый экземпляр Array из итерируемого объекта или объекта, похожего на массив.
Array.fromAsync()
Создает новый экземпляр Array из асинхронного итерируемого объекта, итерируемого объекта или объекта, похожего на массив.
Array.isArray()
Возвращает true, если аргумент является массивом, или false в противном случае.
Array.of()
Создает новый экземпляр Array с переменным числом аргументов, независимо от количества или типа аргументов.

Свойства экземпляра

Эти свойства определены для Array.prototype и разделяются всеми экземплярами Array.

Array.prototype.constructor
Конструкторская функция, которая создала объект экземпляра. Для экземпляров Array начальным значением является конструктор Array.
Array.prototype[Symbol.unscopables]
Содержит имена свойств, которые не были включены в стандарт ECMAScript до версии ES2015 и которые игнорируются для целей привязки with.

Эти свойства являются собственными свойствами каждого экземпляра Array.

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

Методы экземпляра

Array.prototype.at()
Возвращает элемент массива по указанному индексу. Принимает отрицательные целые числа, которые отсчитываются от последнего элемента.
Array.prototype.concat()
Возвращает новый массив, который является результатом объединения вызывающего массива с другими массивами и/или значениями.
Array.prototype.copyWithin()
Копирует последовательность элементов массива внутри массива.
Array.prototype.entries()
Возвращает новый итератор массива, содержащий пары ключ/значение для каждого индекса в массиве.
Array.prototype.every()
Возвращает false, если найден элемент в массиве, который не удовлетворяет предоставленной тестовой функции. В противном случае возвращает true.
Array.prototype.fill()
Заполняет все элементы массива от начального индекса до конечного индекса статическим значением.
Array.prototype.filter()
Возвращает новый массив, содержащий все элементы вызывающего массива, для которых предоставленная функция фильтрации возвращает true.
Array.prototype.find()
Возвращает значение первого элемента в массиве, который удовлетворяет предоставленной тестовой функции, или undefined, если подходящий элемент не найден.
Array.prototype.findIndex()
Возвращает индекс первого элемента в массиве, который удовлетворяет предоставленной тестовой функции, или -1, если подходящий элемент не был найден.
Array.prototype.findLast()
Возвращает значение последнего элемента в массиве, который удовлетворяет предоставленной тестовой функции, или undefined, если подходящий элемент не найден.
Array.prototype.findLastIndex()
Возвращает индекс последнего элемента в массиве, который удовлетворяет предоставленной тестовой функции, или -1, если подходящий элемент не был найден.
Array.prototype.flat()
Возвращает новый массив, в который рекурсивно вложены все подмассивные элементы до указанной глубины.
Array.prototype.flatMap()
Возвращает новый массив, сформированный путем применения предоставленной функции обратного вызова к каждому элементу вызывающего массива, а затем одноуровневого сглаживания результата.
Array.prototype.forEach()
Вызывает функцию для каждого элемента в вызывающем массиве.
Array.prototype.includes()
Определяет, содержит ли вызывающий массив значение, возвращая true или false в зависимости от ситуации.
Array.prototype.indexOf()
Возвращает первый (наименьший) индекс, по которому можно найти данный элемент в вызывающем массиве.
Array.prototype.join()
Возвращает новую строку, которая является результатом конкатенации всех элементов в этом массиве, разделенных запятыми или указанной строкой-разделителем.
Array.prototype.keys()
Возвращает новый итератор массива, содержащий ключи для каждого индекса в вызывающем массиве.
Array.prototype.lastIndexOf()
Возвращает последний (наибольший) индекс, по которому можно найти данный элемент в вызывающем массиве, или -1, если ни один не найден.
Array.prototype.map()
Возвращает новый массив, содержащий результаты вызова функции для каждого элемента в вызывающем массиве.
Array.prototype.pop()
Удаляет последний элемент из массива и возвращает этот элемент.
Array.prototype.push()
Добавляет один или несколько элементов в конец массива и возвращает новую length массива.
Array.prototype.reduce()
Выполняет предоставленную пользователем функцию обратного вызова "редуктора" для каждого элемента массива (слева направо), чтобы свести его к одному значению.
Array.prototype.reduceRight()
Выполняет предоставленную пользователем функцию обратного вызова "редуктора" для каждого элемента массива (справа налево), чтобы свести его к одному значению.
Array.prototype.reverse()
Переворачивает порядок элементов массива на месте. (Первый становится последним, последний становится первым.)
Array.prototype.shift()
Удаляет первый элемент из массива и возвращает этот элемент.
Array.prototype.slice()
Извлекает часть вызывающего массива и возвращает новый массив.
Array.prototype.some()
Возвращает true, если найден элемент в массиве, который удовлетворяет предоставленной тестовой функции. В противном случае возвращает false.
Array.prototype.sort()
Сортирует элементы массива на месте и возвращает массив.
Array.prototype.splice()
Добавляет и/или удаляет элементы из массива.
Array.prototype.toLocaleString()
Возвращает локализованную строку, представляющую вызывающий массив и его элементы. Переопределяет метод Object.prototype.toLocaleString().
Array.prototype.toReversed()
Возвращает новый массив с элементами в обратном порядке, не изменяя исходный массив.
Array.prototype.toSorted()
Возвращает новый массив с элементами, отсортированными в порядке возрастания, не изменяя исходный массив.
Array.prototype.toSpliced()
Возвращает новый массив с удаленными и/или замененными элементами по указанному индексу, не изменяя исходный массив.
Array.prototype.toString()
Возвращает строку, представляющую вызывающий массив и его элементы. Переопределяет метод Object.prototype.toString().
Array.prototype.unshift()
Добавляет один или несколько элементов в начало массива и возвращает новую length массива.
Array.prototype.values()
Возвращает новый итератор массива, содержащий значения для каждого индекса в массиве.
Array.prototype.with()
Возвращает новый массив с элементом по указанному индексу, замененным указанным значением, не изменяя исходный массив.
Array.prototype[Symbol.iterator]()
По умолчанию является псевдонимом для метода values().

Примеры

Этот раздел содержит несколько примеров распространенных операций с массивами в JavaScript.

Примечание: Если вы еще не знакомы с основами массивов, рассмотрите возможность прочтения JavaScript First Steps: Arrays, который объясняет, что такое массивы, и включает другие примеры распространенных операций с массивами.

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

Этот пример показывает три способа создания новых массивов: сначала с использованием нотации литерала массива, затем с использованием конструктора Array(), и, наконец, с использованием String.prototype.split() для построения массива из строки.

// 'fruits' array created using array literal notation.
const fruits = ["Apple", "Banana"];
console.log(fruits.length);
// 2

// 'fruits2' array created using the Array() constructor.
const fruits2 = new Array("Apple", "Banana");
console.log(fruits2.length);
// 2

// 'fruits3' array created using String.prototype.split().
const fruits3 = "Apple, Banana".split(", ");
console.log(fruits3.length);
// 2

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

Этот пример использует метод join() для создания строки из массива fruits.

const fruits = ["Apple", "Banana"];
const fruitsString = fruits.join(", ");
console.log(fruitsString);
// "Apple, Banana"

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

Этот пример показывает, как получить доступ к элементам массива fruits, указав номер индекса его позиции в массиве.

const fruits = ["Apple", "Banana"];

// The index of an array's first element is always 0.
fruits[0]; // Apple

// The index of an array's second element is always 1.
fruits[1]; // Banana

// The index of an array's last element is always one
// less than the length of the array.
fruits[fruits.length - 1]; // Banana

// Using an index number larger than the array's length
// returns 'undefined'.
fruits[99]; // undefined

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

Этот пример использует метод indexOf() для поиска позиции (индекса) строки "Banana" в массиве fruits.

const fruits = ["Apple", "Banana"];
console.log(fruits.indexOf("Banana"));
// 1

Проверка, содержит ли массив определенный элемент

Этот пример показывает два способа проверки, содержит ли массив fruits элементы "Banana" и "Cherry": сначала с помощью метода includes(), а затем с помощью метода indexOf() для проверки значения индекса, которое не является -1.

const fruits = ["Apple", "Banana"];

fruits.includes("Banana"); // true
fruits.includes("Cherry"); // false

// If indexOf() doesn't return -1, the array contains the given item.
fruits.indexOf("Banana") !== -1; // true
fruits.indexOf("Cherry") !== -1; // false

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

Этот пример использует метод push() для добавления новой строки в массив fruits.

const fruits = ["Apple", "Banana"];
const newLength = fruits.push("Orange");
console.log(fruits);
// ["Apple", "Banana", "Orange"]
console.log(newLength);
// 3

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

Этот пример использует метод pop() для удаления последнего элемента из массива fruits.

const fruits = ["Apple", "Banana", "Orange"];
const removedItem = fruits.pop();
console.log(fruits);
// ["Apple", "Banana"]
console.log(removedItem);
// Orange

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

Удаление нескольких элементов из конца массива

Этот пример использует метод splice() для удаления последних 3 элементов из массива fruits.

const fruits = ["Apple", "Banana", "Strawberry", "Mango", "Cherry"];
const start = -3;
const removedItems = fruits.splice(start);
console.log(fruits);
// ["Apple", "Banana"]
console.log(removedItems);
// ["Strawberry", "Mango", "Cherry"]

Усечение массива до первых N элементов

Этот пример использует метод splice() для усечения массива fruits до его первых 2 элементов.

const fruits = ["Apple", "Banana", "Strawberry", "Mango", "Cherry"];
const start = 2;
const removedItems = fruits.splice(start);
console.log(fruits);
// ["Apple", "Banana"]
console.log(removedItems);
// ["Strawberry", "Mango", "Cherry"]

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

Этот пример использует метод shift() для удаления первого элемента из массива fruits.

const fruits = ["Apple", "Banana"];
const removedItem = fruits.shift();
console.log(fruits);
// ["Banana"]
console.log(removedItem);
// Apple

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

Удаление нескольких элементов из начала массива

Этот пример использует метод splice() для удаления первых 3 элементов из массива fruits.

const fruits = ["Apple", "Strawberry", "Cherry", "Banana", "Mango"];
const start = 0;
const deleteCount = 3;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["Banana", "Mango"]
console.log(removedItems);
// ["Apple", "Strawberry", "Cherry"]

Добавление нового первого элемента в массив

Этот пример использует метод unshift() для добавления нового элемента по индексу 0 в массив fruits, делая его новым первым элементом массива.

const fruits = ["Banana", "Mango"];
const newLength = fruits.unshift("Strawberry");
console.log(fruits);
// ["Strawberry", "Banana", "Mango"]
console.log(newLength);
// 3

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

Этот пример использует метод splice() для удаления строки "Banana" из массива fruits, указывая индекс позиции "Banana".

const fruits = ["Strawberry", "Banana", "Mango"];
const start = fruits.indexOf("Banana");
const deleteCount = 1;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["Strawberry", "Mango"]
console.log(removedItems);
// ["Banana"]

Удаление нескольких элементов по индексу

Этот пример использует метод splice() для удаления строк "Banana" и "Strawberry" из массива fruits, указывая индекс позиции "Banana", а также количество удаляемых элементов.

const fruits = ["Apple", "Banana", "Strawberry", "Mango"];
const start = 1;
const deleteCount = 2;
const removedItems = fruits.splice(start, deleteCount);
console.log(fruits);
// ["Apple", "Mango"]
console.log(removedItems);
// ["Banana", "Strawberry"]

Замена нескольких элементов в массиве

Этот пример использует метод splice() для замены последних 2 элементов в массиве fruits новыми элементами.

const fruits = ["Apple", "Banana", "Strawberry"];
const start = -2;
const deleteCount = 2;
const removedItems = fruits.splice(start, deleteCount, "Mango", "Cherry");
console.log(fruits);
// ["Apple", "Mango", "Cherry"]
console.log(removedItems);
// ["Banana", "Strawberry"]

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

Этот пример использует цикл for...of для итерации по массиву fruits, выводя каждый элемент в консоль.

const fruits = ["Apple", "Mango", "Cherry"];
for (const fruit of fruits) {
  console.log(fruit);
}
// Apple
// Mango
// Cherry

Но for...of — лишь один из многих способов итерации по любому массиву; для получения дополнительной информации см. Циклы и итерация, а также документацию по методам every(), filter(), flatMap(), map(), reduce() и reduceRight() — и см. следующий пример, который использует метод forEach().

Вызов функции для каждого элемента в массиве

Этот пример использует метод forEach() для вызова функции для каждого элемента в массиве fruits; функция приводит к выводу каждого элемента в консоль вместе с его номером индекса.

const fruits = ["Apple", "Mango", "Cherry"];
fruits.forEach((item, index, array) => {
  console.log(item, index);
});
// Apple 0
// Mango 1
// Cherry 2

Объединение нескольких массивов

Этот пример использует метод concat() для объединения массива fruits с массивом moreFruits, чтобы получить новый массив combinedFruits. Обратите внимание, что fruits и moreFruits остаются неизменными.

const fruits = ["Apple", "Banana", "Strawberry"];
const moreFruits = ["Mango", "Cherry"];
const combinedFruits = fruits.concat(moreFruits);
console.log(combinedFruits);
// ["Apple", "Banana", "Strawberry", "Mango", "Cherry"]

// The 'fruits' array remains unchanged.
console.log(fruits);
// ["Apple", "Banana", "Strawberry"]

// The 'moreFruits' array also remains unchanged.
console.log(moreFruits);
// ["Mango", "Cherry"]

Копирование массива

Этот пример показывает три способа создания нового массива из существующего массива fruits: сначала с использованием синтаксиса spread, затем с использованием метода from(), и затем с использованием метода slice().

const fruits = ["Strawberry", "Mango"];

// Create a copy using spread syntax.
const fruitsCopy = [...fruits];
// ["Strawberry", "Mango"]

// Create a copy using the from() method.
const fruitsCopy2 = Array.from(fruits);
// ["Strawberry", "Mango"]

// Create a copy using the slice() method.
const fruitsCopy3 = fruits.slice();
// ["Strawberry", "Mango"]

Все встроенные операции копирования массива (синтаксис spread, метод Array.from(), метод Array.prototype.slice() и метод Array.prototype.concat()) создают поверхностные копии. Если вместо этого вам нужна глубокая копия массива, вы можете использовать JSON.stringify() для преобразования массива в строку JSON, а затем JSON.parse() для преобразования строки обратно в новый массив, который полностью независим от исходного массива.

const fruitsDeepCopy = JSON.parse(JSON.stringify(fruits));

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

Наконец, важно понимать, что присвоение существующего массива новой переменной не создает копию ни массива, ни его элементов. Вместо этого новая переменная является просто ссылкой или псевдонимом на исходный массив; то есть имя исходного массива и имя новой переменной — это просто два имени для одного и того же объекта (и поэтому всегда будут оцениваться как строго эквивалентные). Поэтому, если вы внесете какие-либо изменения либо в значение исходного массива, либо в значение новой переменной, другое изменится тоже:

const fruits = ["Strawberry", "Mango"];
const fruitsAlias = fruits;
// 'fruits' and 'fruitsAlias' are the same object, strictly equivalent.
fruits === fruitsAlias; // true
// Any changes to the 'fruits' array change 'fruitsAlias' too.
fruits.unshift("Apple", "Banana");
console.log(fruits);
// ['Apple', 'Banana', 'Strawberry', 'Mango']
console.log(fruitsAlias);
// ['Apple', 'Banana', 'Strawberry', 'Mango']

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

Следующий код создает шахматную доску как двумерный массив строк. Первый ход делается путем копирования 'p' из board[6][4] в board[4][4]. Старая позиция в [6][4] становится пустой.

const 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`);

// Move King's Pawn forward 2
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

Использование массива для табулирования набора значений

const values = [];
for (let x = 0; x < 10; x++) {
  values.push([2 ** x, 2 * x ** 2]);
}
console.table(values);

Результат:

// The first column is the index
0  1    0
1  2    2
2  4    8
3  8    18
4  16   32
5  32   50
6  64   72
7  128  98
8  256  128
9  512  162

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

Результат совпадения между RegExp и строкой может создать массив JavaScript, который имеет свойства и элементы, предоставляющие информацию о совпадении. Такой массив возвращается методами RegExp.prototype.exec() и String.prototype.match().

Например:

// Match one d followed by one or more b's followed by one d
// Remember matched b's and the following d
// Ignore case

const myRe = /d(b+)(d)/i;
const execResult = myRe.exec("cdbBdbsbz");

console.log(execResult.input); // 'cdbBdbsbz'
console.log(execResult.index); // 1
console.log(execResult); // [ "dbBd", "bB", "d" ]

Для получения дополнительной информации о результате совпадения см. страницы RegExp.prototype.exec() и String.prototype.match().

Изменение исходного массива в итеративных методах

Итеративные методы не изменяют массив, к которому они применяются, но функция, предоставленная как callbackFn, может. Ключевой принцип, который следует помнить, заключается в том, что посещаются только индексы между 0 и arrayLength - 1, где arrayLength — это длина массива на момент вызова метода массива, но элемент, передаваемый в обратный вызов, — это значение на момент посещения индекса. Следовательно:

  • callbackFn не будет посещать никакие элементы, добавленные после начальной длины массива при начале вызова итеративного метода.
  • Изменения в уже посещенных индексах не вызывают повторного вызова callbackFn для них.
  • Если существующий, еще не посещенный элемент массива изменяется с помощью callbackFn, его значение, переданное в callbackFn, будет значением на момент посещения этого элемента. Удаленные элементы не посещаются.

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

В следующих примерах в качестве примера используется метод forEach, но другие методы, которые посещают индексы в порядке возрастания, работают аналогично. Сначала мы определим вспомогательную функцию:

function testSideEffect(effect) {
  const arr = ["e1", "e2", "e3", "e4"];
  arr.forEach((elem, index, arr) => {
    console.log(`array: [${arr.join(", ")}], index: ${index}, elem: ${elem}`);
    effect(arr, index);
  });
  console.log(`Final array: [${arr.join(", ")}]`);
}

Изменения в еще не посещенных индексах будут видимы при достижении индекса:

testSideEffect((arr, index) => {
  if (index + 1 < arr.length) arr[index + 1] += "*";
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2*, e3, e4], index: 1, elem: e2*
// array: [e1, e2*, e3*, e4], index: 2, elem: e3*
// array: [e1, e2*, e3*, e4*], index: 3, elem: e4*
// Final array: [e1, e2*, e3*, e4*]

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

testSideEffect((arr, index) => {
  if (index > 0) arr[index - 1] += "*";
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2, e3, e4], index: 1, elem: e2
// array: [e1*, e2, e3, e4], index: 2, elem: e3
// array: [e1*, e2*, e3, e4], index: 3, elem: e4
// Final array: [e1*, e2*, e3*, e4]

Вставка n элементов по непосещенным индексам, которые меньше начальной длины массива, приведет к их посещению. Последние n элементов в исходном массиве, которые теперь имеют индекс больше начальной длины массива, не будут посещены:

testSideEffect((arr, index) => {
  if (index === 1) arr.splice(2, 0, "new");
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2, e3, e4], index: 1, elem: e2
// array: [e1, e2, new, e3, e4], index: 2, elem: new
// array: [e1, e2, new, e3, e4], index: 3, elem: e3
// Final array: [e1, e2, new, e3, e4]
// e4 is not visited because it now has index 4

Вставка n элементов с индексом, превышающим начальную длину массива, не приведет к их посещению:

testSideEffect((arr) => arr.push("new"));
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2, e3, e4, new], index: 1, elem: e2
// array: [e1, e2, e3, e4, new, new], index: 2, elem: e3
// array: [e1, e2, e3, e4, new, new, new], index: 3, elem: e4
// Final array: [e1, e2, e3, e4, new, new, new, new]

Вставка n элементов по уже посещенным индексам не приведет к их посещению, но сдвинет оставшиеся элементы назад на n, поэтому текущий индекс и n - 1 элементов перед ним будут посещены снова:

testSideEffect((arr, index) => arr.splice(index, 0, "new"));
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [new, e1, e2, e3, e4], index: 1, elem: e1
// array: [new, new, e1, e2, e3, e4], index: 2, elem: e1
// array: [new, new, new, e1, e2, e3, e4], index: 3, elem: e1
// Final array: [new, new, new, new, e1, e2, e3, e4]
// e1 keeps getting visited because it keeps getting shifted back

Удаление n элементов по непосещенным индексам приведет к тому, что они больше не будут посещаться. Поскольку массив уменьшился, последние n итераций будут посещать индексы за пределами диапазона. Если метод игнорирует несуществующие индексы (см. методы массива и пустые слоты), последние n итераций будут пропущены; в противном случае они получат undefined:

testSideEffect((arr, index) => {
  if (index === 1) arr.splice(2, 1);
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2, e3, e4], index: 1, elem: e2
// array: [e1, e2, e4], index: 2, elem: e4
// Final array: [e1, e2, e4]
// Does not visit index 3 because it's out-of-bounds

// Compare this with find(), which treats nonexistent indexes as undefined:
const arr2 = ["e1", "e2", "e3", "e4"];
arr2.find((elem, index, arr) => {
  console.log(`array: [${arr.join(", ")}], index: ${index}, elem: ${elem}`);
  if (index === 1) arr.splice(2, 1);
  return false;
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e1, e2, e3, e4], index: 1, elem: e2
// array: [e1, e2, e4], index: 2, elem: e4
// array: [e1, e2, e4], index: 3, elem: undefined

Удаление n элементов по уже посещенным индексам не изменяет того факта, что они были посещены до их удаления. Поскольку массив уменьшился, следующие n элементов после текущего индекса пропускаются. Если метод игнорирует несуществующие индексы, последние n итераций будут пропущены; в противном случае они получат undefined:

testSideEffect((arr, index) => arr.splice(index, 1));
// array: [e1, e2, e3, e4], index: 0, elem: e1
// Does not visit e2 because e2 now has index 0, which has already been visited
// array: [e2, e3, e4], index: 1, elem: e3
// Does not visit e4 because e4 now has index 1, which has already been visited
// Final array: [e2, e4]
// Index 2 is out-of-bounds, so it's not visited

// Compare this with find(), which treats nonexistent indexes as undefined:
const arr2 = ["e1", "e2", "e3", "e4"];
arr2.find((elem, index, arr) => {
  console.log(`array: [${arr.join(", ")}], index: ${index}, elem: ${elem}`);
  arr.splice(index, 1);
  return false;
});
// array: [e1, e2, e3, e4], index: 0, elem: e1
// array: [e2, e3, e4], index: 1, elem: e3
// array: [e2, e4], index: 2, elem: undefined
// array: [e2, e4], index: 3, elem: undefined

Для методов, которые итерируют в порядке убывания индексов, вставка приводит к пропуску элементов, а удаление — к многократному посещению элементов. Настройте код выше самостоятельно, чтобы увидеть эффекты.

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

Спецификация
ECMAScript® 2027 Language Specification
# sec-array-objects

Совместимость с браузерами

Desktop Mobile Server
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet WebView Android WebView on iOS Bun Deno Node.js
Array
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
@@iterator
38
12
36
27–36A placeholder property named @@iterator is used.
17–27A placeholder property named iterator is used.
25
10
38
36
27–36A placeholder property named @@iterator is used.
17–27A placeholder property named iterator is used.
25
10
3.0
38
10
1.0.0
1.0
0.12.0
@@species
51
79
48
38
10
51
48
41
10
5.0
51
10
1.0.0
1.0
6.5.0
@@unscopables
38
12
48
25
10
38
48
25
10
3.0
38
10
1.0.0
1.0
0.12.0
Array
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
at
92
92
90
78
15.4
92
90
65
15.4
16.0
92
15.4
1.0.0
1.12
16.6.0
concat
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
copyWithin
45
12
32
32
9
45
32
32
9
5.0
45
9
1.0.0
1.0
4.0.0
entries
38
12
28
25
8
38
28
25
8
3.0
38
8
1.0.0
1.0
0.12.0
every
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
fill
45
12
31
32
8
45
31
32
8
5.0
45
8
1.0.0
1.0
4.0.0
filter
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
find
45
12
25
32
8
45
4
32
8
5.0
45
8
1.0.0
1.0
4.0.0
findIndex
45
12
25
32
8
45
4
32
8
5.0
45
8
1.0.0
1.0
4.0.0
findLast
97
97
104
83
15.4
97
104
68
15.4
18.0
97
15.4
1.0.0
1.16
18.0.0
findLastIndex
97
97
104
83
15.4
97
104
68
15.4
18.0
97
15.4
1.0.0
1.16
18.0.0
flat
69
79
62
56
12
69
62
48
12
10.0
69
12
1.0.0
1.0
11.0.0
flatMap
69
79
62
56
12
69
62
48
12
10.0
69
12
1.0.0
1.0
11.0.0
forEach
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
from
45
12
32
32
9
45
32
32
9
5.0
45
9
1.0.0
1.0
4.0.0
fromAsync
121
121
115
107
16.4
121
115
81
16.4
25.0
121
16.4
1.0.0
1.38
22.0.0
includes
47
14
43
34
9
47
43
34
9
5.0
47
9
1.0.0
1.0
6.0.0
indexOf
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
isArray
4
12
4
10.5
5
18
4
14
5
1.0
4.4
5
1.0.0
1.0
0.10.0
join
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
keys
38
12
28
25
8
38
28
25
8
3.0
38
8
1.0.0
1.0
0.12.0
lastIndexOf
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
length
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
map
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
of
45
12
25
26
9
39
25
26
9
4.0
39
9
1.0.0
1.0
4.0.0
pop
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
push
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
reduce
3
12
3
10.5
4
18
4
14
3.2
1.0
4.4
3.2
1.0.0
1.0
0.10.0
reduceRight
3
12
3
10.5
4
18
4
14
3.2
1.0
4.4
3.2
1.0.0
1.0
0.10.0
reverse
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
shift
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
slice
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
some
1
12
1.5
9.5
3
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
sort
1
12
1
4
1
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
splice
1
12
1
4
1
18
4
10.1
1
1.0
4.4
1
1.0.0
1.0
0.10.0
toLocaleString
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
toReversed
110
110
115
96
16
110
115
74
16
21.0
110
16
1.0.0
1.31
20.0.0
toSorted
110
110
115
96
16
110
115
74
16
21.0
110
16
1.0.0
1.31
20.0.0
toSpliced
110
110
115
96
16
110
115
74
16
21.0
110
16
1.0.0
1.31
20.0.0
toString
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
unshift
1
12
1
4
1
18
4
10.1
1
1.0
1
1
1.0.0
1.0
0.10.0
values
66
14
60
53
9
66
60
47
9
9.0
66
9
1.0.0
1.0
10.9.0
0.12.0–4.0.0
with
110
110
115
96
16
110
115
74
16
21.0
110
16
1.0.0
1.31
20.0.0

См. также

  • Руководство по индексированным коллекциям
  • TypedArray
  • ArrayBuffer

© 2005–2025 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API