slice и splice звучат похоже, но делают разные вещи.
- slice - возвращает часть массива (копию) и не изменяет исходный массив
- splice - удаляет/вставляет элементы и изменяет исходный массив
Это один из самых важных моментов в работе с массивами.
slice: взять кусок массива без изменений
Синтаксис:
arr.slice(start, end)
start- индекс, с которого начинать (включительно)end- индекс, на котором остановиться (не включительно)- если
endне указан, берется до конца
Пример: часть массива
const items = ["a", "b", "c", "d"];
const part = items.slice(1, 3);
console.log(part); // ["b", "c"]
console.log(items); // ["a", "b", "c", "d"]
Копия всего массива
slice() без аргументов делает поверхностную копию массива:
const a = [1, 2, 3];
const b = a.slice();
b[0] = 99;
console.log(a); // [1, 2, 3]
console.log(b); // [99, 2, 3]
Отрицательные индексы
Отрицательные индексы считают с конца.
const items = ["a", "b", "c", "d"];
console.log(items.slice(-2)); // ["c", "d"]
console.log(items.slice(0, -1)); // ["a", "b", "c"]
splice: удалить или вставить и изменить массив
Синтаксис:
arr.splice(start, deleteCount, ...itemsToInsert)
start- индекс, с которого начать измененияdeleteCount- сколько элементов удалитьitemsToInsert- что вставить (необязательно)- метод возвращает массив удаленных элементов
Удаление элементов
const items = ["a", "b", "c", "d"];
const removed = items.splice(1, 2);
console.log(removed); // ["b", "c"]
console.log(items); // ["a", "d"]
Удалить один элемент по индексу
const items = ["a", "b", "c"];
const removed = items.splice(1, 1);
console.log(removed); // ["b"]
console.log(items); // ["a", "c"]
Вставка без удаления
Если deleteCount равен 0, ничего не удаляется, только вставляется.
const items = ["a", "d"];
items.splice(1, 0, "b", "c");
console.log(items); // ["a", "b", "c", "d"]
Замена элементов
Удаление и вставка одновременно - это замена.
const items = ["a", "b", "c", "d"];
items.splice(1, 2, "x", "y");
console.log(items); // ["a", "x", "y", "d"]
Удалить до конца
Если не указать deleteCount, будет удалено все от start до конца.
const items = ["a", "b", "c", "d"];
const removed = items.splice(2);
console.log(removed); // ["c", "d"]
console.log(items); // ["a", "b"]
Поверхностная копия: важный нюанс
slice делает поверхностную копию. Если внутри массива лежат объекты, копируются ссылки, а не “глубокие” данные.
const a = [{ n: 1 }, { n: 2 }];
const b = a.slice();
b[0].n = 99;
console.log(a[0].n); // 99
console.log(b[0].n); // 99
Копия массива есть, но объекты внутри - те же самые.
Когда что использовать
sliceподходит, когда нужна копия или подмассив без изменений исходного массива.spliceподходит, когда нужно изменить массив: удалить, вставить или заменить элементы по индексу.
Практичное правило: если после операции исходный массив должен остаться прежним - нужен slice (или другие не-мутирующие методы). Если массив должен поменяться - splice.
Частые ошибки
1) Путаница с end в slice
end не включается. Это часто вызывает off-by-one.
const items = ["a", "b", "c", "d"];
console.log(items.slice(1, 2)); // ["b"]
2) Неожиданное изменение массива из-за splice
splice меняет массив. Если исходный массив используется дальше, это может быть проблемой.
const items = ["a", "b", "c"];
const removed = items.splice(1, 1);
console.log(items); // ["a", "c"]
console.log(removed); // ["b"]
Что стоит запомнить
sliceне меняет массив и возвращает копию (часть массива).spliceменяет массив и возвращает удаленные элементы.slice(start, end)берет элементы отstartдоend(end не включается).splice(start, deleteCount, ...items)удаляет и/или вставляет элементы.sliceкопирует массив поверхностно: вложенные объекты остаются общими по ссылке.