JavaScript: Let’s implement Array.slice() and Array.splice()

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto
Published in
8 min readAug 1, 2020

--

Previously, we have implemented Array methods:

  • map and sort
  • filter and concat
  • reduceRight

Here, we continue with the implementation. We will take on splice and slice.

POSTly is a web-based API tool that allows for fast testing of your APIs (REST, GraphQL). Check it out here:

splice and slice

Splice

Removes elements from an array and, if necessary inserts new elements in their place and returns the deleted elements.

(method) Array.splice(start: number, deleteCount?:number, ...items: number[]): number[]

start the zero-based location in the array from which to start removing elements.

deleteCount the number of elements to remove.

items elements to insert into the array in place of the deleted elements.

Let’s see examples.

We have an array:

const arr = [56, 66, 99, 44]

If we want to splice the array from the second index.

arr.splice(1)

splice will start from 66 and get the elements until it reaches element 44 the end of the array.

The elements will be returned:

[ 66, 99, 44 ]

Note : splice doesn’t get a section of the array. It cuts from the start index to the end of the array.

Using the arr, we can cut from the third index:

arr.splice(2)

Index 2 will start from element 99, so splice will start from element 99 to 44 and return them:

[ 99, 44 ]

Splicing from index 3 will start from 44 to the end of the array.

arr.splice(3)|----->
index => 0 1 2 3
const arr = [56, 66, 99, 44]

It will return:

[ 44 ]

What happens if we want to start from a negative index?

Splice will reverse the order of index numbering.

index starts from left to right, but passing a negative index will make splice start from the right to left.

Example:

const arr = [56, 66, 99, 44]
l(arr.splice(-3))

We passed a negative index to splice -3 here.

splice will start from right down:

|----------->
index => -4 -3 -2 -1
const arr = [56, 66, 99, 44]

See the index doesn’t start from 0 but from -1 down.

So, splice(-3) will start from element 66 to element 44:

[ 66, 99, 44 ]

Splice(-2) will be

|----------->
index => -4 -3 -2 -1
const arr = [56, 66, 99, 44]

The result:

[ 99, 44 ]

Splice(-4) will be

|--------------->
index => -4 -3 -2 -1
const arr = [56, 66, 99, 44]

It will start from element 56 to element 44:

[ 56, 66, 99, 44 ]

What happens if we pass start index that doesn’t exist?

Example in our arr array:

const arr = [56, 66, 99, 44]

And we want to slice from index 5. Now array index has no index 5. It only has index 0, 1, 2, 3.

Any reference after 3 will return undefined. When passed to splice, it will return the whole array.

arr.splice(5)

Result:

[ 56, 66, 99, 44 ]

Passing negatives indices will return the whole array too.

arr.splice(-5)

This is a negative index but not in range of arr negative indices it has.

index => -4 -3 -2 -1
const arr = [56, 66, 99, 44]

The negative indices on arr start from -1,-2, -3, -4. There is no -5

So, arr.splice(-5) will return the whole array:

[ 56, 66, 99, 44 ]

Setting the number of elements to remove from the spliced array

We will pass a second param to splice to set the number of elements to splice from an array.

const arr = [56, 66, 99, 44]l(arr.splice(1, 2))

This will start from index 1 ie element 66, and cut two elements towards right:

|-->-|
index => 0 1 2 3
const arr = [56, 66, 99, 44]

The 2 we passed to splice made it splice two elements, if we had passed 3, it will cut three elements from index 1.

The result:

[ 66, 99 ]

Can we insert elements inside the deleted elements?

Yes, splice allows us to do just that by specifying a third optional argument. This third argument holds the elements to add in the place of the deleted elements.

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(1, 3, 0, 1)

This will cut the array from index 1 to index 3. The remaining argument in the splice call: 0, 1 will be added to the space deleted from the arr array.

First, splice(1, 3) will make array arr to be:

arr = [56]

Then 0 and 1 will be added to it.:

arr = [56, 0, 1]

while the result spliceArr will hold the result of splice(1,3)

spliceArr = [66, 99, 44]

If we run it:

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(1, 3, 0, 1)
l("arr: ", arr)
l("spliceArr: ", spliceArr)

The result:

$ node array
arr: [ 56, 0, 1 ]
spliceArr: [ 66, 99, 44 ]

Splice: Mutability

Is splice a mutating method or non-mutating? Let’s find out.

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(2)
l("arr: " + arr, "spliceArr: " + spliceArr)
l(arr === spliceArr)

The result

$ node array
arr: 56,66 spliceArr: 99,44
false

We see that arr has been mutated. It’s data structure/info/composition has been changed.

splice affected the original array, arr. So we know that splice is a mutating method.

Important Note

If we pass deleteCount to splice. It(splice) will cut off the specified deleteCount from the array and stuff back the remaining back to the original array.

Example:

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(1,2)

This will cut the arr from element 66 to element 44, then will delete two elements from the extracted array.

Implementing splice

Armed with what we have known of the splice method we implement our own:

Let’s test our implementation:

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(1, 2, 0, 1)l(arr)
l(spliceArr)

Result:

$ node array
[ 56, 0, 1, 44 ]
[ 66, 99 ]

Same result with the original splice implementation. Also, it mutates the original array, here arr data structure was changed.

Another test:

const arr = [56, 66, 99, 44]const spliceArr = arr.splice(1, 2)l(arr)
l(spliceArr)

Result:

$ node array
[ 56, 44 ]
[ 66, 99 ]

Slice returns a section of an array

(method) Array<number>.slice(start? : number, end?: number): number[]

start the beginning of the specified portion of the array.

end is the end of the specified portion of the array

slice cuts from the index specified by start.

const brr = [56, 66, 99, 44]const marr = brr.slice(1)l(marr)

Result:

[ 66, 99, 44 ]

We sliced from index 1. So it will start from element 66, which is at index 1, to the end of the array at element 44.

|----------> 
index => 0 1 2 3
const brr = [56, 66, 99, 44]

The elements [66, 99, 44] will be returned.

If we specify an end index, slice will cut from the start index and stop at the index next to meet the end index.

const brr = [56, 66, 99, 44]const marr = brr.slice(1, 2)l(brr)

This will start from index 1, element 66 and stop at index 1. An index short of the end index, 2. The element at index 2 (99) won’t be included.

So the result will be this:

[ 66 ]

If we make the end index to be 3:

const brr = [56, 66, 99, 44]const marr = brr.slice(1, 3)

It will start at index 1 (66) and stop at index 2 (99).

[ 66, 99 ]

Negative index

What happens when we pass a negative index?

slice will convert it to its positive index. How?

slice counts postive index (from 0) from left to right. slice counts negative index from (starting from -1, -2) right to left:

-ve index => -4 -3 -2 -1
+ve index => 0 1 2 3
const brr = [ 56, 66, 99, 44 ]

So if we do this:

const marr = brr.slice(-3)

slice will start from -ve index -3, which is 1 on the +ve index, and cut to the right.

|----------->
-ve index => -4 -3 -2 -1
+ve index => 0 1 2 3
const brr = [ 56, 66, 99, 44 ]
[ 66, 99, 44 ]

Adding end index at the negative index:

const brr = [56, 66, 99, 44]const marr = brr.slice(-3, 3)

slice will start from index 1 (converting negative index -3 to its +ve index relative) and stop at index 2:

|---|
-ve index => -4 -3 -2 -1
+ve index => 0 1 2 3
const brr = [ 56, 66, 99, 44 ]
[ 66, 99 ]

Mutability

Is slice a mutating or non-mutating method? Let’s find out:

const brr = [56, 66, 99, 44]const marr = brr.slice(1, 3)const sliceArr = brr.slice(1, 3)l("brr:", brr)
l("sliceArr:", sliceArr)
l(brr === sliceArr)

Result:

brr: [ 56, 66, 99, 44 ]
sliceArr: [ 66, 99 ]
false

See the brr array from which we sliced wasn’t changed. It remained the same, unscathed ;)

Implementation

Test:

const brr = [56, 66, 99, 44]const sliceArr = brr.slice(-3)l("brr:", brr)
l("sliceArr:", sliceArr)

Result:

$ node array
brr: [ 56, 66, 99, 44 ]
sliceArr: [ 66, 99, 44 ]

Boom, the result is the same as the original slice method. Also, notice the original array, arr was not mutated.

Conclusion

I’ll say this is awesome.

Remember, "What I do not understand, I cannot create."

If you have comments, suggestions, corrections, or just wanna talk feel free to drop in the comments section or DM me or e-mail.

Thanks!!

Thanks for stopping by my little corner of the web. I think you’ll love my email newsletter about programming advice, tutoring, tech, programming and software development. Just sign up below:

Follow me on Twitter.

--

--

Chidume Nnamdi 🔥💻🎵🎮
Dev Proto

JS | Blockchain dev | Author of “Understanding JavaScript” and “Array Methods in JavaScript” - https://app.gumroad.com/chidumennamdi 📕