Array.prototype.slice copies a contiguous range of elements into a new array and leaves the original untouched. The end index is exclusive, negative indices count from the end, and the copy is shallow—nested objects are still shared references. When you need mutating removal or insertion in the middle of an array, use splice instead; for “drop the last element” without mutation, slice(0, -1) pairs naturally with pop semantics.
Tested on: Node.js v20.18.2. A short note after each snippet describes what you should see in the console.
Quick reference
slice never mutates the receiver; splice mutates and returns removed elements. Typed arrays add subarray (shared buffer) versus slice (copy).
| Method | Mutates original? | Typical return |
|---|---|---|
slice |
No | New array (or typed array) with selected elements |
splice |
Yes | Array of removed elements |
subarray (typed) |
No (but shares buffer) | New view on same buffer |
filter |
No | New array matching predicate |
slice(start, end) — javascript slice array basics
end is exclusive. The original array is unchanged.
let myArray = [1, 2, 3, 4, 5];
let slicedArray = myArray.slice(1, 3);
console.log(slicedArray, myArray);You should see one line like: [ 2, 3 ] [ 1, 2, 3, 4, 5 ].
Negative indices — js array slicing
Negative start / end count backward from length, so you can trim ends without computing indexes by hand.
console.log([1, 2, 3, 4, 5].slice(1, -1));
console.log([1, 2, 3, 4, 5].slice(-2));You should see 2 lines: [ 2, 3, 4 ], then [ 4, 5 ].
Shallow copy of the whole array — slice array javascript clone
Calling slice() with no arguments copies the whole array (shallowly).
console.log([1, 2, 3].slice());You should see one line like: [ 1, 2, 3 ].
Nested structures are still shared by reference; slice is not a deep clone.
splice — not the same as slice (array slicing javascript pitfall)
splice(start, deleteCount) removes deleteCount elements at start and returns those elements; it mutates the array.
let myArray = [1, 2, 3, 4, 5];
let removed = myArray.splice(1, 3);
console.log(removed, myArray);You should see one line like: [ 2, 3, 4 ] [ 1, 5 ].
This is not “slice with inclusive end”; the second argument is how many to delete, not an end index.
Typed arrays: subarray vs slice
TypedArray.prototype.subarray returns a view on the same buffer (mutations can alias the original). slice on a typed array copies the range into a new typed array.
const u = new Uint8Array([1, 2, 3, 4]);
const s = u.slice(1, 3);
s[0] = 99;
const u2 = new Uint8Array([1, 2, 3, 4]);
const sb = u2.subarray(1, 3);
sb[0] = 88;
console.log("sliceBuf", u, s);
console.log("subBuf", u2, sb);You should see 2 lines: sliceBuf Uint8Array(4) [ 1, 2, 3, 4 ] Uint8Array(2) [ 99, 3 ], then subBuf Uint8Array(4) [ 1, 88, 3, 4 ] Uint8Array(2) [ 88, 3 ].
Plain slice on a Uint8Array (same numeric range as the opening subarray example):
const myArray = new Uint8Array([10, 20, 30, 40, 50]);
let slicedArray = myArray.slice(1, 4);
console.log(slicedArray);You should see one line like: Uint8Array(3) [ 20, 30, 40 ].
filter — index-based slice-like ranges
Prefer slice when you only need a contiguous index range; use filter when the condition is more complex.
let myArray = [1, 2, 3, 4, 5];
let slicedArray = myArray.filter((_, index) => index >= 1 && index < 3);
console.log(slicedArray);You should see one line like: [ 2, 3 ].
Generic Array.prototype.slice.call — js slice array on array-like
slice is generic: with .call, you can materialize an array from an array-like object with a length.
console.log(Array.prototype.slice.call({ 0: "a", 1: "b", length: 2 }, 0, 1));You should see one line like: [ 'a' ].
Summary
Think slice = copy a range, splice = edit in place; negative indices and exclusive end match other Array APIs, while typed-array subarray still shares storage.
slice(start, end)copies a half-open range and never mutates the source array.- Negative indices count from the end;
slice()clones the whole array shallowly. splicedeletes in place and returns removed elements—different arguments thanslice.- On typed arrays,
subarrayshares a buffer;slicecopies. Usefilteronly when selection is not a simple range.
References
MDN references for slice, splice, typed-array views, and filter.
- MDN:
Array.prototype.slice() - MDN:
Array.prototype.splice() - MDN:
TypedArray.prototype.subarray() - MDN:
TypedArray.prototype.slice() - MDN:
Array.prototype.filter()
Frequently Asked Questions
Does javascript array slice change the original array?
No. slice returns a new array (shallow copy of the selected range). The original length and elements stay the same unless you use a mutating method like splice.
What is the difference between slice and splice in javascript slice array tutorials?
slice(start, end) copies elements from start up to but not including end. splice(start, deleteCount, ...items) removes deleteCount elements at start, optionally inserts new items, and mutates the original array. splice returns the removed elements as an array.
How do negative indexes work for js array slice?
Negative start or end counts from the end: index length + negative. For example, slice(1, -1) drops the first and last elements of a non-empty array.
How do I clone an array with array slice javascript?
Call slice with no arguments: const copy = arr.slice(). This is a shallow copy: nested objects or arrays are still shared references.
TypedArray subarray vs slice for array slicing javascript?
subarray(start, end) returns another view on the same underlying buffer; mutating an element in the view can change the original typed array. slice returns a new typed array with copied elements in that range, so mutating the slice does not change the source buffer through that slice.
javascript array.slice moz style semantics for end index?
end is always exclusive, whether positive or negative, matching ECMAScript and MDN.
