How to shift array position in vanilla JavaScript
Tags: javascript, node, programming, webdev
Published: 2018-12-19 08:44:47

I was helping a user over at [sanity.io](https://www.sanity.io) yesterday doing some content migration, where they wanted to take the last element of an array and put it in the first position. Every time I get a question like this, I like to see if I manage to solve it without going to any libraries. Both because I don't want to introduce more dependencies for the person with the question, but most of all, it's an opportunity for some mental exercise. 

So, how to change an array like this: 

```js
["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]
```

to this?

```js
["Walder", "Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn"]
```

My first instinct was to make a new array just targeting the last element with the list length subtracted by 1, and then spreading the rest of the array using `splice`. Push the green *run* button to run the code:

{% runkit %}
const theList = ["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]

const newList = [theList[theList.length - 1], ...theList.splice(0, theList.length - 1)]

console.log(newList)
{% endrunkit %}

Some of you will already have guessed why this is a bad idea, and some of you will be like me and always mix up `splice` and `slice`. Let’s see what happens with `theList` when we *run* the code above:

{% runkit 
const theList = ["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]
const newList = [theList[theList.length - 1], ...theList.splice(0, theList.length - 1)]
%}
// check output
console.log(newList)
// check output
console.log(theList)
{% endrunkit %}

Not ideal (unless you're Arya). Replacing `splice` with `slice` leaves the original array intact, and will not mutate it (which can lead to a mountain of problems):

{% runkit 
const theList = ["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]
%}
const newList = [theList[theList.length - 1], ...theList.slice(0, theList.length - 1)]

console.log(newList)
console.log(theList)
{% endrunkit %}


This leaves us with exactly what we want. 

Another way to go about it is to use the `Array.prototype.reduce`-method, which to me feel a bit cleaner. Also, `.reduce` is worth investing time into learning. 

{% runkit 
const theList = ["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]
%}
const newList = theList.reduce(
  (accumulatedArray, currentItem, index, originalArray) =>
    index < originalArray.length - 1
      ? [...accumulatedArray, currentItem]
      : [currentItem, ...accumulatedArray],
  []
)

console.log(newList)
console.log(theList)
{% endrunkit %}

This can, of course, be made into a function. Tempting as it may be, I don't recommend using an _anonymous_ arrow (`=>`) function for this, as it doesn't show up with a name in the console stack trace if something wrong occurs: 

{% runkit 
const theList = ["Cersei", "Joffrey", "Ilyn", "The Mountain", "The Hound", "Melisandre", "Beric", "Thoros", "Tywin", "Meryn", "Walder"]
%}
function shiftLastToFirst (theArray) {
  return theArray.reduce(
    (accumulatedArray, currentItem, index, originalArray) => {
      return index < originalArray.length - 1
        ? [...accumulatedArray, currentItem]
        : [currentItem, ...accumulatedArray]
    },
    []
  )
}
shiftLastToFirst(theList)
{% endrunkit %}

Now, I'm certain there are many smarter ways of doing this. And the reason I'm writing this up and putting it here is that I want to learn about them. 

How would you go about solving this?