Массивы предоставляют множество методов. Чтобы было проще, в этой главе они разбиты на группы.
Добавление/удаление элементов
Мы уже знаем методы, которые добавляют и удаляют элементы из начала или конца:
arr.push(...items)
– добавляет элементы в конец,arr.pop()
– извлекает элемент из конца,arr.shift()
– извлекает элемент из начала,arr.unshift(...items)
– добавляет элементы в начало.
Есть и другие.
splice
Как удалить элемент из массива?
Так как массивы – это объекты, то можно попробовать delete
:
let arr = ["I", "go", "home"];
delete arr[1]; // удалить "go"
alert( arr[1] ); // undefined
// теперь arr = ["I", , "home"];
alert( arr.length ); // 3
Вроде бы, элемент и был удалён, но при проверке оказывается, что массив всё ещё имеет 3 элемента arr.length == 3
.
Это нормально, потому что всё, что делает delete obj.key
– это удаляет значение с данным ключом key
. Это нормально для объектов, но для массивов мы обычно хотим, чтобы оставшиеся элементы сдвинулись и заняли освободившееся место. Мы ждём, что массив станет короче.
Поэтому для этого нужно использовать специальные методы.
Метод arr.splice(str) – это универсальный «швейцарский нож» для работы с массивами. Умеет всё: добавлять, удалять и заменять элементы.
Его синтаксис:
arr.splice(index[, deleteCount, elem1, ..., elemN])
Он начинает с позиции index
, удаляет deleteCount
элементов и вставляет elem1, ..., elemN
на их место. Возвращает массив из удалённых элементов.
Этот метод проще всего понять, рассмотрев примеры.
Начнём с удаления:
let arr = ["Я", "изучаю", "JavaScript"];
arr.splice(1, 1); // начиная с позиции 1, удалить 1 элемент
alert( arr ); // осталось ["Я", "JavaScript"]
Легко, правда? Начиная с позиции 1
, он убрал 1
элемент.
В следующем примере мы удалим 3 элемента и заменим их двумя другими.
let arr = ["Я", "изучаю", "JavaScript", "прямо", "сейчас"];
// удалить 3 первых элемента и заменить их другими
arr.splice(0, 3, "Давай", "танцевать");
alert( arr ) // теперь ["Давай", "танцевать", "прямо", "сейчас"]
Здесь видно, что splice
возвращает массив из удалённых элементов:
let arr = ["Я", "изучаю", "JavaScript", "прямо", "сейчас"];
// удалить 2 первых элемента
let removed = arr.splice(0, 2);
alert( removed ); // "Я", "изучаю" <-- массив из удалённых элементов
Метод splice
также может вставлять элементы без удаления, для этого достаточно установить deleteCount
в 0
:
let arr = ["Я", "изучаю", "JavaScript"];
// с позиции 2
// удалить 0 элементов
// вставить "сложный", "язык"
arr.splice(2, 0, "сложный", "язык");
alert( arr ); // "Я", "изучаю", "сложный", "язык", "JavaScript"
Отрицательные индексы разрешены
В этом и в других методах массива допускается использование отрицательного индекса. Он позволяет начать отсчёт элементов с конца, как тут:
let arr = [1, 2, 5];
// начиная с индекса -1 (перед последним элементом)
// удалить 0 элементов,
// затем вставить числа 3 и 4
arr.splice(-1, 0, 3, 4);
alert( arr ); // 1,2,3,4,5
slice
Метод arr.slice намного проще, чем похожий на него arr.splice
.
Его синтаксис:
arr.slice([start], [end])
Он возвращает новый массив, в который копирует элементы, начиная с индекса start
и до end
(не включая end
). Оба индекса start
и end
могут быть отрицательными. В таком случае отсчёт будет осуществляться с конца массива.
Это похоже на строковый метод str.slice
, но вместо подстрок возвращает подмассивы.
Например:
let arr = ["t", "e", "s", "t"];
alert( arr.slice(1, 3) ); // e,s (копирует с 1 до 3)
alert( arr.slice(-2) ); // s,t (копирует с -2 до конца)
Можно вызвать slice
и вообще без аргументов: arr.slice()
создаёт копию массива arr
. Это часто используют, чтобы создать копию массива для дальнейших преобразований, которые не должны менять исходный массив.
concat
Метод arr.concat создаёт новый массив, в который копирует данные из других массивов и дополнительные значения.
Его синтаксис:
arr.concat(arg1, arg2...)
Он принимает любое количество аргументов, которые могут быть как массивами, так и простыми значениями.
В результате мы получаем новый массив, включающий в себя элементы из arr
, а также arg1
, arg2
и так далее…
Если аргумент argN
– массив, то все его элементы копируются. Иначе скопируется сам аргумент.
Например:
let arr = [1, 2];
// создать массив из: arr и [3,4]
alert( arr.concat([3, 4]) ); // 1,2,3,4
// создать массив из: arr и [3,4] и [5,6]
alert( arr.concat([3, 4], [5, 6]) ); // 1,2,3,4,5,6
// создать массив из: arr и [3,4], потом добавить значения 5 и 6
alert( arr.concat([3, 4], 5, 6) ); // 1,2,3,4,5,6
Обычно он просто копирует элементы из массивов. Другие объекты, даже если они выглядят как массивы, добавляются как есть:
let arr = [1, 2];
let arrayLike = {
0: "что-то",
length: 1
};
alert( arr.concat(arrayLike) ); // 1,2,[object Object]
…Но если объект имеет специальное свойство Symbol.isConcatSpreadable
, то он обрабатывается concat
как массив: вместо него добавляются его числовые свойства.
Для корректной обработки в объекте должны быть числовые свойства и length
:
let arr = [1, 2];
let arrayLike = {
0: "что-то",
1: "ещё",
[Symbol.isConcatSpreadable]: true,
length: 2
};
alert( arr.concat(arrayLike) ); // 1,2,что-то,ещё