Table of Contents

The JavaScript Array slice() method returns a shallow copy of a selected part of an array. It does not change the original array, which makes it useful when you need to read or copy values without altering the source. You choose the range with a starting index and an optional ending index.

This tutorial explains the syntax, indexes, return value, negative positions, common patterns, and how slice() differs from splice().

Syntax

array.slice(start, end)

start is the index where the copied range begins. end is the index where it stops, but the element at that index is not included. Both arguments are optional: omitting start begins at index 0, and omitting end copies through the end of the array.

Array indexes are zero-based, so index 0 is the first element. In slice(1, 4), the range includes index 1 and stops before index 4.

Basic example

const fruits = ["Apple", "Banana", "Mango", "Orange", "Grapes"];

const selected = fruits.slice(1, 4);

console.log(selected); // ["Banana", "Mango", "Orange"]
console.log(fruits);   // ["Apple", "Banana", "Mango", "Orange", "Grapes"]

The new array contains the values at indexes 1, 2, and 3. Index 4, which contains “Grapes,” is excluded. The original fruits array remains unchanged.

Understanding start and end

Start index

A non-negative start counts from the beginning. If it is greater than the array’s length, the result is an empty array because there are no elements at or after that position.

A negative start counts backward from the end: -1 refers to the last element, -2 to the second-to-last, and so on. If it goes farther back than the array’s length, the start is treated as 0.

const colors = ["red", "green", "blue", "gold"];

console.log(colors.slice(2));    // ["blue", "gold"]
console.log(colors.slice(-2));   // ["blue", "gold"]
console.log(colors.slice(-20));  // ["red", "green", "blue", "gold"]

End index

A non-negative end also counts from the beginning and is exclusive. A negative end counts backward from the end. If end is omitted, the method copies through the last element. If the calculated end position is before the start position, slice() returns an empty array.

const letters = ["a", "b", "c", "d", "e"];

console.log(letters.slice(1, 4));   // ["b", "c", "d"]
console.log(letters.slice(1, -1));  // ["b", "c", "d"]
console.log(letters.slice(-4, -1)); // ["b", "c", "d"]
console.log(letters.slice(3, 1));   // []

Using a negative end is a convenient way to exclude values from the tail. For example, slice(0, -1) returns everything except the last item.

Return value

slice() always returns a new array containing the selected elements. If the range has no elements, the result is []. Since it does not modify the source array, you can store the result while keeping the original available for later operations.

const numbers = [10, 20, 30, 40];

const firstTwo = numbers.slice(0, 2);
firstTwo.push(99);

console.log(firstTwo); // [10, 20, 99]
console.log(numbers);  // [10, 20, 30, 40]

In this example, push() changes the copied array only. The source array is still the same.

Copying an array

Call slice() with no arguments to make a shallow copy of the entire array. You can also use slice(0); both forms select every element.

const original = ["tea", "coffee", "juice"];
const copy = original.slice();

copy[0] = "water";

console.log(copy);     // ["water", "coffee", "juice"]
console.log(original); // ["tea", "coffee", "juice"]

This is a shallow copy: the outer array is new, but nested objects or arrays are not duplicated. If an element is an object, both arrays still refer to that same object.

const users = [{ name: "Mina" }];
const usersCopy = users.slice();

usersCopy[0].name = "Rafi";
console.log(users[0].name); // "Rafi"

Changing a top-level slot in the copy does not replace the corresponding slot in the original. Changing a property on a shared nested object is visible through both arrays. Use a suitable deep-copy approach only when you specifically need independent nested data.

Useful array slicing examples

Get the first few elements

Set the end index to the number of values you want. Since the end is exclusive, slice(0, 3) returns the first three elements.

const scores = [92, 85, 78, 96, 88];
const topThree = scores.slice(0, 3);

console.log(topThree); // [92, 85, 78]

Get the last few elements

A negative start counts from the end, so slice(-2) returns the last two items regardless of the array’s length.

const months = ["Jan", "Feb", "Mar", "Apr", "May"];
console.log(months.slice(-3)); // ["Mar", "Apr", "May"]

Copy a range between positions

Use both indexes to select a middle section. Remember that the second index marks where the selection stops.

const days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
const workdays = days.slice(0, 5);

console.log(workdays); // ["Mon", "Tue", "Wed", "Thu", "Fri"]

Remove an item without changing the original

You can combine two slices to create a new array that leaves out one position. The first slice gets the values before the item; the second gets the values after it.

const items = ["pen", "notebook", "ruler", "eraser"];
const indexToSkip = 1;

const updated = [
  ...items.slice(0, indexToSkip),
  ...items.slice(indexToSkip + 1)
];

console.log(updated); // ["pen", "ruler", "eraser"]
console.log(items);   // ["pen", "notebook", "ruler", "eraser"]

For a simple new array made by excluding values that match a condition, filter() is often easier to read. This two-slice pattern is useful when you already know the exact index.

slice() vs. splice()

The names are similar, but the methods do different jobs. slice() copies a range and leaves the original array alone. splice() edits the original array by removing, inserting, or replacing elements. It returns the elements removed.

const letters = ["a", "b", "c", "d"];

const part = letters.slice(1, 3);
console.log(part);    // ["b", "c"]
console.log(letters); // ["a", "b", "c", "d"]

const removed = letters.splice(1, 2);
console.log(removed); // ["b", "c"]
console.log(letters); // ["a", "d"]

Choose slice() when you need a separate range or copy. Choose splice() when the existing list itself should change. In newer environments, toSpliced() offers splice-like edits while returning a new array instead of mutating the original.

Create a new array with an item inserted

slice() can help build a new array with a value inserted at a chosen index while leaving the original unchanged. Copy the elements before the position, add the new value, then copy the elements from that position onward. The spread syntax combines those pieces into one array.

const tasks = ["plan", "code", "review"];
const index = 1;
const updated = [
  ...tasks.slice(0, index),
  "test",
  ...tasks.slice(index)
];

console.log(updated); // ["plan", "test", "code", "review"]
console.log(tasks);   // ["plan", "code", "review"]

This pattern inserts before the value that currently occupies index. Use index 0 to add at the beginning, or tasks.length to append. Keep the index between 0 and the array length so that the two ranges meet at the intended position.

Build a replacement array

You can replace the value at a known index by copying the range before it, adding the replacement, and then copying from the next index. The original remains available for comparison or reuse.

const colors = ["red", "green", "blue"];
const indexToReplace = 1;
const updatedColors = [
  ...colors.slice(0, indexToReplace),
  "gold",
  ...colors.slice(indexToReplace + 1)
];

console.log(updatedColors); // ["red", "gold", "blue"]
console.log(colors);        // ["red", "green", "blue"]

For repeated edits or more complex conditions, consider a method designed for that job, such as map() for transforming values or filter() for excluding them. These slice patterns are most readable when the index is already known and you want a new array rather than an in-place change.