The JavaScript array slice
method is one of the most powerful and commonly used built-ins in the JavaScript language.
And with the rise of React and other functionally oriented JavaScript practices, it is becoming even more important, for 2 key reasons:
- Functional programming, particularly higher level functions, works heavily with lists of data
- Functional programming requires pure functions, functions that do not cause side effects or modify their input data.
The JavaScript array slice
method fits both of these criteria.
The slice
method provides a mechanism for creating a shallow copy of a subset of a list, without modifying the original list. Thus it provides a key building block for writing functional JavaScript.
In this post we'll master the slice
method by example, exploring 8 different ways it can be used.
Caution: The slice
method is not to be confused with the splice
method, which modifies an array in place.
Slice leaves the original array intact and returns a shallow copy of selected items, splice modifies the original array.
How Javascript Array Slice Works
Before we dive into some of the more advanced uses, lets look at the basics of the slice
method.
As shown in the MDN documentation, slice
isa method on an array that takes up to 2 arguments:
arr.slice([begin[, end]])
The begin
argument is a 0-based index identifying where to begin extraction, while the end
argument is a 0-based index identifying where to end.
The slice
method creates a copy of the array starting at begin
up to but not including end
.
It also accepts negative indices, which indicate counts back from the end of the array.
Basic Uses
Our first 4 uses highlight the core functionality of slice
.
Use 1: Simple copy
const arr2 = arr.slice();
Slice without any arguments performs a simple shallow copy. In modern JavaScript it is more idiomatic to use the spread operator for this functionality, but if working in older codebases or without a build step that uses babel you may still want to use slice
.
Use 2: Subarray starting at N
The simplest way to use the slice
method is simply to grab all elements of an array starting at N.
An example use case might be you want to pop off the first element of an array and use it, returning the remaining array, but you want to do it without modifying the original array.
function useOne(arr) {
const usedItem = arr[0];
// do something with usedItem
return arr.slice(1);
}
Use 3: last N of an array
Another way that slice
can be used is to grab the end of an array, taking advantage of the fact that negative indexes count back from the end.
This negative indexing makes it super simple to strip off however many elements you want. For example, if you want to grab just 3:
const last3 = arr.slice(-3)
Use 4: first n of an array
The pull off the front of an array, we need to start using the second argument to the method as well: end
.
When both arguments are passed, the slice
method returns a set starting at begin
up to but not including end
.
Since JavaScript arrays are zero-based (index starts at 0), this makes it super simple to pull off the first N elements:
const first4 = arr.slice(0, 4)
Use 5: inner segment of n, starting at m
Generalizing use 5, what if we want to use slice
to pull off a segment of the array starting at any index?
To do this, we need to translate from (begin, length)
, to (begin, end)
. Luckily, the math is straightforward and we can define a simple function to do this:
function pullSegment(arr, begin, length) {
return arr.slice(begin, begin + length);
}
Working With Array-like Objects
The slice
method can also be used on array-like objects. These are objects that behave mostly like arrays, but are not actually arrays. These are essentially any object that includes a length
value and can be accessed via numerical indexes, but do not include Array methods.
Some examples include arguments
(keyword for accessing all arguments passed to a function), NodeLists
(returned from any DOM API method that returns a list of nodes), and even raw objects that use numerical indices and add a length
attribute.
To use the slice
method on an array-like object, you need to reference it directly from Array.prototype
, like this:
Array.prototype.slice.call(arguments);
This leads to a couple valuable uses:
Use 6: Convert array-like objects into arrays
One common use for the Slice operator on array-like objects is to convert them into actual arrays. For example:
const args = Array.prototype.slice.call(arguments);
Why would you want to do this? To get access to array methods. For example, imagine a function that looks like this:
function addOne() {
return arguments.map(i => i+1);
}
Seems like it would work, but if you try to do this you get:
> addOne(1, 2, 3)
TypeError: arguments.map is not a function
at test (repl:2:18)
at repl:1:1
at ContextifyScript.Script.runInThisContext (vm.js:44:33)
at REPLServer.defaultEval (repl.js:239:29)
at bound (domain.js:301:14)
at REPLServer.runBound [as eval] (domain.js:314:12)
at REPLServer.onLine (repl.js:440:10)
at emitOne (events.js:120:20)
at REPLServer.emit (events.js:210:7)
at REPLServer.Interface._onLine (readline.js:279:10)
This is because arguments
is not actually an array, but an array-like object. You can implement this function using slice
as follows:
function addOne() {
return Array.prototype.slice.call(arguments).map(i => i+1);
}
and now you get what you'd expect:
> addOne(1, 2, 3)
[2, 3, 4]
Use 7: Coerce arbitrary length extra arguments into an array
Sometimes you want to allow for arbitrary numbers of arguments to a function.
Newer versions of JavaScript have introduced what is known as rest syntax to handle this, but if you are stuck supporting older browsers without a transpilation system, you can do this with slice
:
function myFunc(a, b) {
const extraArgs = Array.prototype.slice.call(arguments, 2);
}
This allows calling myFunc with arbitrary numbers of args. e.g.:
myFunc(1, 2, 3, 4, 5, 6, 7, 8)
And inside you'll end up with a === 1
, b === 2
, and extraArgs === [3, 4, 5, 6, 7, 8]
Functional Array Manipulation
Another huge area of use for slice
is to manipulate arrays in a functional/pure way, without modifying the original array.
Use 8: modifying a particular index in an array
A powerful and common use of slice
in a functional context is to replace the value of a particular item in an array.
Imperatively this is simple, you just assign the new value, but in a functional world you can't modify the original array.
Instead, you can combine slice
with the new JavaScript spread operator to return a new array that is identical but for the index you want to update:
function replaceIdx(arr, index, newVal) {
return [
...arr.slice( 0, index ),
newVal,
...arr.slice( index + 1)
],
}
Partial Function Application
Another common pattern in functional programming is what is known as partial function application: pre-applying parameters to a function, and then returning a new function.
This pattern allows you to compose functions, creating greater reusability by letting you use the same core functions with different pre-applied parameters.
While more pure functional languages like Haskell support partial function application natively, in JavaScript we can implement a function to do it using slice
:
var partial = function() {
const fn = arguments[0];
const args = Array.prototype.slice.call(arguments, 1);
// Return a function that calls fn
return function() {
var remainingArgs = Array.prototype.slice.call(arguments);
return fn.apply(this, args.concat(remainingArgs));
}
}
Wrapping Up
As you can see by this point, the Array slice
method is an incredibly useful tool in your JavaScript toolchest, especially as you start moving towards more functional ways of programming.
I'm confident there are many more great examples of using slice
- if you have a good one, share it in the comments below! I'll happily update the post.
P.S. - If you're interested in these types of topics, you should probably follow me on Twitter or join my mailing list. I send out a weekly newsletter called the ‘Friday Frontend’. Every Friday I send out 15 links to the best articles, tutorials, and announcements in CSS/SCSS, JavaScript, and assorted other awesome Front-end News. Sign up here: https://zendev.com/friday-frontend.html
Top comments (0)