Skip to main content
Refine AI
How to Use JavaScript Slice Method
15 min read

How to Use JavaScript Slice Method

This article was last updated on November 4, 2024 to include advanced use cases and improve the organization for a clearer understanding of the JavaScript slice() method.

Introduction

This post is about the JavaScript slice method, where we explore Array.prototype.slice and String.prototype.slice in depth.

The JavaScript Iteration Methods Series covers posts on iteration methods that are used to loop over a collection of data to act on the items or produce side effects from them. Iteration operations, especially with arrays and strings, are very common in front end development with libraries like React and Angular.js.

Steps we'll cover:

What is Iteration ?

Iteration is the process of looping through a collection of data and performing action on each item in order to manipulate it or create a side effect from it. Common examples of iteration methods in JavaScript are Array.prototype.forEach, Array.prototype.map and Array.prototype.reduce.

There are other iteration methods which are not as often used, but when needed are always handy tools for iterating over arrays, strings and objects. JavaScript slice(), some() and every() are such examples.

JavaScript Iteration Methods: Complete vs Partial Iteration

Some iteration methods, like Array.prototype.forEach and Array.prototype.map iterate over all items in a collection. Others like Array.prototype.slice, Array.prototype.includes or Array.prototype.some iterate over the array partially, if not required completely.

Overview

In this post, we look into the details of using JavaScript slice which is an iteration method available with identical implementations in Array and String prototypes. We get into the nuances of the two versions with examples involving both of these object types.

We set off with an example that expounds some general cases for selecting and storing a section from a source array. Then we see a couple of more interesting examples that help us generate arrays from arguments passed to a function using Function.prototype.call and Function.prototype.bind.

Towards the end, we explore the usage and quirks of the String version of JavaScript slice with examples of extracting substrings from a source string.

Let's start with the array version of Javascript slice().

JS Slice - Array.prototype.slice

This section covers the usage of Array version of JavaScript slice().

What is JavaScript Array slice ?

Array.prototype.slice is a JS Array method that is used to extract a contiguous subarray or "slice" from an existing array.

JavaScript slice can take two arguments: the start and the end indicator of the slice -- both of which are optional. It can also be invoked without any argument. So, it has the following call signatures:

// Method signature

slice();
slice(start);
slice(start, end);

Slicing an Array: How to Use JavaScript slice

A typical example of slicing an array involves producing a contiguous section from a source array. For example, the first three items, last three items and some items spanning from a certain index up until another index.

As shown in the examples below:

const elements = [
"Please",
"Send",
"Cats",
"Monkeys",
"And",
"Zebras",
"In",
"Large",
"Cages",
"Make",
"Sure",
"Padlocked",
];

const firstThree = elements.slice(0, 3);
const lastThree = elements.slice(-3, elements.length);
const fromThirdToFifth = elements.slice(2, 5);

Both arguments of slice() stand for zero-based index numbers. Negative values denote offset from the end of the array.

The first argument (0 in the firstThree assignment above) represents the starting index or offset in the source array where slicing should begin. The second argument (3) is the index or offset before which extraction should stop.

If we log the extracted values above, we can see the three elements we want for each slice:

console.log(firstThree); // ["Please", "Send", "Cats"]
console.log(lastThree); // ["Make", "Sure", "Padlocked"]
console.log(fromThirdToFifth); // ["Cats", "Monkeys", "And"]

It is important to notice that the item represented by the second argument is excluded from the extracted slice.

JavaScript Array slice vs splice

We should also note that unlike in Array.prototype.splice, the second argument of Array.prototype.slice does not stand for the number of items to be extracted. In JavaScript splice, the second argument is rather the count of items to be deleted, as opposed to being extracted.

Array.prototype.splice is very dissimilar from Array.prototype.slice because JavaScript splice() mutates the original array, whereas slice() creates a copy.

Nuances of JavaScript Array.prototype.slice

The sections below highlight with examples the nuances of how the JS Array slice method behaves in scenarios with different argument values.

JavaScript Array slice with No Arguments

If we don't pass any argument to JavaScript slice, we get a shallow copy of the source array with all items:

const allCopied = elements.slice();

console.log(allCopied);
// (12) ["Please", "Send", "Cats", "Monkeys", "And", "Zebras", "In", "Large", "Cages", "Make", "Sure", "Padlocked"]

It's effectively [...elements].

JavaScript Array slice Method with No Second Argument

If we don't pass the second argument, the extracted JavaScript Array slice extends to the last element:

const fromThird = elements.slice(2);
const lastThree = elements.slice(-3, elements.length);
const lastThreeWithNoSecArg = elements.slice(-3);

console.log(fromThird);
// (10) ["Cats", "Monkeys", "And", "Zebras", "In", "Large", "Cages", "Make", "Sure", "Padlocked"]
console.log(lastThree); // (3) ["Make", "Sure", "Padlocked"]
console.log(lastThreeWithNoSecArg); // (3) ["Make", "Sure", "Padlocked"]

Notice that lastThreeWithNoSecArg evaluates to the same slice as lastThree, albeit missing the second argument.

JavaScript Array.prototype.slice with Negative Offsets

Notice also above that, we can pass in negative numbers as arguments. Negative values of the arguments denote offset positions counted backwards from the last item. We can do this for both arguments:

const latestTwoBeforeLast = elements.slice(-3, -1);
console.log(latestTwoBeforeLast); // (2) ["Make", "Sure"]

Here, with latestTwoBeforeLast, we're getting the last two items prior to the final one.

JS Array.prototype.slice: Starting Position Greater Than End Position

If we pass in a greater value for start than end, we get an empty array:

const somewhereWeDontKnow = elements.slice(5, 2);
console.log(somewhereWeDontKnow); // []

This indicates we have to always start slicing from a lesser positive index.

Array.prototype.slice: Starting Position Greater Than Length of Array

Likewise, if we pass in a greater value for start than array's length, we get an empty array:

const somewhereInOuterSpace = elements.slice(15, 2);
console.log(somewhereInOuterSpace); // []

Using JS slice with Sparse Arrays

If our target slice has sparse items, they are also copied over:

const elements = [
"Please",
"Send",
,
"Cats",
,
"Monkeys",
"And",
"Zebras",
"In",
"Large",
"Cages",
"Make",
"Sure",
"Padlocked",
];

const sparseItems = elements.slice(0, 6);

console.log(sparseItems);
// (6) [ 'Please', 'Send', <1 empty item>, 'Cats', <1 empty item>, 'Monkeys' ]

Array.prototype.slice: Creating Arrays from a List of Arguments

In this section we go a bit crazy about slicing. We develop two interesting ways with Array.prototype.slice to construct an array from a list of arguments passed to a function.

The first one:

const createArray = (...args) => Array.prototype.slice.call(args);
const array = createArray(1, 2, 3, 4);
console.log(array); // (4) [1, 2, 3, 4]

Here, we received args as a list first, but converted it to an array with rest params ...args. We then bound the array to Array.prototype.slice with Function.prototype.call and stored the function in createArray.

Invoking createArray with a list of arguments places them inside args and a copy of it is created with Array.prototype.slice. So, we get the new array as output.

That was easy.

The next level way of doing this is in the messiest possible way:

const boundSlice = Function.prototype.call.bind(Array.prototype.slice);

const createArray = (...args) => boundSlice(args);

const array = createArray(1, 2, 3, 4);
console.log(array); // (4) [1, 2, 3, 4]

It seems like an overhead, but what we are doing is declaring two helper functions.

The first one, boundSlice, is derived from binding the Function.prototype.call method with Function.prototype.bind to Array.prototype.slice which is an array function object. So, we are getting a copy of Function.prototype.call bound to Array.prototype.slice and storing it in boundSlice.

This basically means, if we invoke boundSlice(), we are in effect invoking Array.prototype.slice.call. When we then pass in an array to boundSlice(), Array.prototype.slice is invoked and a copy is created from it.

In createArray(), we are accumulating the items as rest arguments and passing them to boundSlice() as args array. So, whatever we pass to createArray() is returned as items inside an array copied from args.

When to use JavaScript slice method?

  1. Creating a Subset of an Array: If you need a portion of an array without changing the original array, slice is the ideal choice.

  2. Copying an Array: slice can be used to create a shallow copy of an entire array. This is useful when you want to work with a copy of an array and leave the original array unchanged.

  3. String Manipulation: While often associated with arrays, slice is also applicable to strings. It's used to extract a substring from a string, based on the start and end indices provided.

  4. Creating Paginated Data: When implementing pagination, slice can be used to get the subset of data that should be displayed on the current page.

  5. Removing Elements Conditionally: While slice itself doesn't remove elements, it can be used in combination with other methods to conditionally remove elements from an array.

  6. Non-Destructive Array Manipulation: In scenarios where you need to ensure the original data structure remains unchanged, slice is preferable over methods like splice which modify the array in place.

  7. Working with the arguments Object: In functions, to convert the arguments object into a real array, slice can be used. This allows you to use Array methods on arguments.

JS String Slice - String.prototype.slice

In this section, we explore the String version of JavaScript slice() method with examples of creating substrins from a source string.

String.prototype.slice does the exact same thing as Array.prototype.slice, but with characters in a string as items.

Like Array.prototype.slice, it takes two optional arguments, start and end. And it works without an argument as well:

// Method signature

slice();
slice(start);
slice(end);

Slicing a JavaScript String: How to Use String.prototype.slice

String.prototype.slice is useful for directly working on strings. It removes the hassle of converting a string to an array with String.prototype.split.

It can be used like below:

const mnemonic =
"Please Send Cats Monkeys And Zebras In Large Cages Make Sure Padlocked";

const firstThreeChars = mnemonic.slice(0, 3);
const lastThreeChars = mnemonic.slice(-3, mnemonic.length);
const fromThirdToFifthChars = mnemonic.slice(2, 5);

console.log(firstThreeChars); // "Ple"
console.log(lastThreeChars); // "ked"
console.log(fromThirdToFifthChars); // "eas"

Again, both arguments represent zero-based index numbers or offset values. Here too, the first argument -- 0 in the firstThree assignment -- stands for the starting index or offset in the source array. And the second argument (3) denotes the index or offset before which extraction should stop.

Advanced Use Cases for slice() - JavaScript

I wanted to share a few interesting ways one might apply the slice() method in JavaScript, other than how it's usually used. These examples might turn out handy, especially when working with more complex data.

Array Flattening

When one deals with a nested array and wants to extract a certain subarray, slice() works without touching the original structure. Say you are working with just a few items at each nested level; slice() can be used in a selectivity manner, to keep all things tidy and restrict the unwarranted changes to the main array.

const nestedArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
const slicedSubarray = nestedArray
.slice(0, 2)
.map((innerArr) => innerArr.slice(1));
console.log(slicedSubarray); // [[2, 3], [5, 6]]

Working with Array-like Objects

Array-like objects, such as the arguments in a function or NodeLists within a DOM, do not have all the various methods of arrays by default. Using the slice() method upon these can change them into real arrays, thereby opening many more functionalities. This is a neat way to deal with such structures without extra loops or conversions.

function getArgumentsArray() {
return Array.prototype.slice.call(arguments);
}
const argsArray = getArgumentsArray(1, 2, 3);
console.log(argsArray); // [1, 2, 3]

Using slice() with Immutability

If you are working with libraries like Redux that rely on immutability, then it's a good use case for shallow copying arrays with slice(), so you can update or do whatever you want with the data copy, leaving the original copy unchanged. This is the easy way out to keep your code predictable and functional programming principles conformant.

const originalArray = [1, 2, 3, 4, 5];
const modifiedArray = originalArray.slice(0, 3).concat([10, 11]);
console.log(modifiedArray); // [1, 2, 3, 10, 11]
console.log(originalArray); // [1, 2, 3, 4, 5]

Using slice() in these methods has helped clean up code and make it more trustworthy, as well as offering far more control over the data.

JavaScript String Slice Nuances

Using JavaScript String slice With No Arguments

Similar to Array slice, if we don't pass any argument to String slice(), the whole string is copied over:

const mnemonic =
"Please Send Cats Monkeys And Zebras In Large Cages Make Sure Padlocked";
const memorizedMnemonic = mnemonic.slice();

console.log(memorizedMnemonic);
// "Please Send Cats Monkeys And Zebras In Large Cages Make Sure Padlocked"

JS String slice with No Second Argument

Here again, if we don't pass the second argument, the copied string extends to the end of the string:

const charsFromThird = mnemonic.slice(2);

console.log(charsFromThird);
// "ease Send Cats Monkeys And Zebras In Large Cages Make Sure Padlocked"

JavaScript String slice with Negative Offsets

Similar to Array.prototype.slice, negative values for start and end represent offset positions from the end of the array:

const mnemonic =
"Please Send Cats Monkeys And Zebras In Large Cages Make Sure Padlocked";

const lastThreeChars = mnemonic.slice(-3);
const latestTwoCharsBeforeLast = mnemonic.slice(-3, -1);

console.log(lastThreeChars); // "ked"
console.log(latestTwoCharsBeforeLast); // "ke"

JS String slice with Higher Starting Positions

Again, if start is greater than end or the length of string, we get an empty string:

const inAnotherDimension = mnemonic.slice(5, 2);
const doingStringTheory = mnemonic.slice(15, 2);

console.log(inAnotherDimension); // ""
console.log(doingStringTheory); // ""

Best Practices Using JavaScript slice()

Here's a quick look at how to avoid some common mistakes with JavaScript slice() and get the most out of it. Best practices like these will help you keep your code clean and predictable, especially in projects where immutability and data integrity are valued.

Use slice() for Immutability

slice() is perfect when one needs to make a copy of an array without touching the original. If, for instance, you have state in some sort of Redux store or similar environment, slice() will allow you to keep the original:

const originalArr = [1, 2, 3];
const copyArr = originalArr.slice();
copyArr.push(4);
console.log(originalArr); // [1, 2, 3]
console.log(copyArr); // [1, 2, 3, 4]

Combine slice() with Other Array Methods

The slice() method works well with methods like map() or filter() when you want to modify or extract part of an array without touching the whole thing. Here's an example:

const arr = [1, 2, 3, 4, 5];
const modifiedSubset = arr.slice(1, 4).map((num) => num * 2);
console.log(modifiedSubset); // [4, 6, 8]

Such an approach is especially convenient for creating views or paginated data sets from larger arrays.

Handle Sparse Arrays with Care

One thing to notice: slice() keeps empty (sparse) array slots, and this can create some surprising behavior if you're dealing with incomplete data sets. If you want to lose those blank items, you can compose slice() with filter(Boolean):

const sparseArr = [1, , 3, , 5];
const cleanArr = sparseArr.slice().filter(Boolean);
console.log(cleanArr); // [1, 3, 5]

This keeps the array clean without gaps, making it easier to process or display consistently.

Using these techniques with slice() can make your code more readable and help avoid some of the widely occurring array problems.

Summary

In this post, we expounded the slice() method in JavaScript. We saw that JavaScript implements slice() in two flavors: one for Arrays with Array.prototype.slice and one for Strings with String.prototype.slice. We found out through examples that both methods produce a copy of the source object and they are used to extract a target contiguous slice from it.

We covered a couple of examples of how function composition and context binding with Function.prototype.call and Function.prototype.bind allows us to define custom functions using Array.prototype.slice to help us generate arrays from a list of arguments.

We also saw that String.prototype.slice is an identical implementation of Array.prototype.slice that removes the overhead of converting a string to an array of characters.