• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

I Like Kill Nerds

The blog of Australian Front End / Aurelia Javascript Developer & brewing aficionado Dwayne Charrington // Aurelia.io Core Team member.

  • Home
  • Aurelia 2
  • Aurelia 1
  • About
  • Aurelia 2 Consulting/Freelance Work

Efficiently Looping A Javascript Array Backwards

Javascript · March 16, 2017

Most of the time when you’re looping over an array of elements, you’ll do it sequentially. However, I recently needed to iterate through an array of objects in reverse just using a plain old for loop.

This will not be a highly informative or groundbreaking post but, I thought I’d share this in case someone wants to solve the same problem and might be confused with the many different ways you can loop over an array in reverse.

I had an idea in mind, I knew Array.reverse would be the ideal candidate but I still Googled to see if smarter developers than me figured something better out.

Turns out, there are a lot of scary alternatives to looping an array in reverse (mostly on StackOverflow). Some people are proponents of decrementing and using while loops, others had different ideas. Why not just use a function that’s existed since the dawn of Javascript?

var myItems = [
    {name: 'Dwayne'},
    {name: 'Rob'},
    {name: 'Marie'},
    {name: 'Sarah'},
    {name: 'Emma'},
    {name: 'James'}
];

var itemsToIterate = myItems.slice(0).reverse();

for (var i = 0, len = itemsToIterate.length; i < len; i++) {
    var item = itemsToIterate[i];
}

In our example, we take an array of items and then we use slice to make a copy of our array starting at its first index (zero). Then we call reverse on the cloned array.

I said efficient in the title, but I haven’t benchmarked anything. However, we are using a barebones for loop and you don’t really get much faster than that. Sometimes commonsense and readability beat microoptimisating.

The reason we copy the array is so we don’t modify the original array. Using slice allows us to effectively clone the array and gives us a new instance, there are other ways of doing the same thing but I find this way is the cleanest.

Without slice, you’ll be modifying the provided value to our function and might produce an unintended result doing so. I tend to keep my functions pure for this kind of thing, nothing that gets input should be modified.

Thanks to reverse flipping our array upside down, we iterate like we would normally. Breaking out the reverse functionality into a function might also be a great idea. This would allow us to easily test our functionality from within a unit test.

function reverseArray(array) {
    return array.slice(0).reverse();
}

One thing to keep in mind is for my use-case, slice worked — if you’re dealing with arrays containing object references or nested arrays or complex objects, slice does not do a deep copy.

Lodash has some great methods for doing recursive and deep cloning of arrays and collections if you need that kind of power. Post your thoughts and suggestions in the comments below.

Dwayne

Leave a Reply Cancel reply

9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Martijn
Martijn
6 years ago

Hi Dwayne,

I was wondering, why not just do it like:

for( var i = myItems.length-1; i >= 0; i– ) {
console.log(myItems[i]);
}

4
Dwayne
Dwayne
Author
6 years ago

Hi Martijn,

That would work too. The solution I ended up using just feels more simple, I find decrementing to look a bit harsh on the eyes. Whereas, the reverse method just looks cleaner and it’s easier to understand what’s going on.

-2
Aziz
Aziz
6 years ago

Hi Dwayne,
I also wonder if this would work…

var itemsToIterate = myItems.slice(0);

while(itemsToIterate.length != 0 )
var item = itemsToIterate.pop();

0
Chris "2pha" Brown
Chris "2pha" Brown
5 years ago

Efficient?
How about?

var i = myItems.length;
while (i–) {
console.log(myItems[i].name);
}

1
Layl Bongers
Layl Bongers
5 years ago

“Efficiently Looping” you’re cloning an entire array, which is probably one of the least efficient operations you could be doing to achieve this.

6
Rob
Rob
5 years ago

Layl, did you even read the article? Dwayne clones the array ONCE. This is just so the original array is not mutated, so you’re making changes to a new array. It’s a standard thing many of us do. You don’t get anymore efficient than a for loop.

-1
Layl Bongers
Layl Bongers
5 years ago

The for loop’s efficiency is dwarfed by the cost of allocating the memory for a new array and copying over all the values. With a small array and with most javascript applications this cost is going to be negligible, but it’s not “Efficient”. A simple decrementing for loop avoids the cost of this all-together. This is certainly an easily understandable solution, but it’s not efficient.

4
YamiteruXYZ
YamiteruXYZ
5 years ago

Hi, the fastest way is to use while instead of for like this:

function reverseLoop(arr = [], fn = (item) => {console.log(item);}) {
let l = arr.length;
while(l–) {
fn(arr[l]);
}
}

For: 765,714 op/sec.
While: 439,365,249 op/sec.

Seeing this humongous difference in performance you could tweak the previous function a bit like this:

function loop(arr, fn = (item) => {console.log(item);}, reverse=true) {
if(!arr || !arr.length) return;
if(!!reverse) arr.reverse();
let l = arr.length;
while(l–) {
fn(arr[l]);
}
}

0
Hamza
Hamza
5 years ago

YamiteruXYZ I don’t think yours is any better, I’ve used the performance.now() API to mesure execution time:
1- using a normal while loop:
Call to while took 2.299999992828816 milliseconds.
2- using a normal for loop:
Call to for took 2.3999999975785613 milliseconds.
3-using your reverseLoop():
Call to reverseLoop took 2.7999999874737114 milliseconds.
4-using your loop():
Call to loop took 10.399999999208376 milliseconds.
So simply put it’s way better to just use a while or a for loop.

1

Primary Sidebar

Popular

  • Testing Event Listeners In Jest (Without Using A Library)
  • How To Get The Hash of A File In Node.js
  • Thoughts on the Flipper Zero
  • Waiting for an Element to Exist With JavaScript
  • How To Paginate An Array In Javascript
  • Handling Errors with the Fetch API
  • ChatGPT Stopping Part Way Through a Response? Here Is How You Fix It
  • How To Get Last 4 Digits of A Credit Card Number in Javascript
  • How to Use Neural DSP Archetype Plugins With the Quad Cortex
  • How To Mock uuid In Jest

Recent Comments

  • CJ on Microsoft Modern Wireless Headset Review
  • Dwayne on Microsoft Modern Wireless Headset Review
  • CJ on Microsoft Modern Wireless Headset Review
  • john on Microsoft Modern Wireless Headset Review
  • Dwayne on Why You Should Be Using globalThis Instead of Window In Your Javascript Code

Copyright © 2023 · Dwayne Charrington · Log in

wpDiscuz