January 2022

Shuffle An Array in JavaScript

Updated: March, 2026

Random History

bittybitty provides a .shuffle() function for arrays. It uses the Fisher–Yates/Knuth shuffleshuffle algorithm. Knuth shuffle sounds like a dance from the mid 20th century, but it's a way to jumble an array using a random number generator.

I've used JavaScript's Math.random() to generate those numbers for years. For bitty, I put in an upgrade.

crypto, not crypto

JavaScript has had a better way to generate random numbers since 2015history. It's called crypto.getRandomValues() and I never see it mentionedstuck.

This version of crypto is not a currency. It's a way to generate "cryptographically strong random values".

Random Changes

Using Math

The old Math.random()js version of the function looks like this:

JavaScript

function shuffleWithMath(array) {
  for (let i = array.length - 1; i >= 1; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [array[i], array[j]] = [array[j], array[i]];
  }
}

JavaScript

const items = ["alfa", "bravo", "charlie", "delta", "echo"];
shuffleWithMath(items);
const mathRandomOutput = document.querySelector("#mathRandomOutput");
mathRandomOutput.innerHTML = items.join(" - ");

Math.random() Output

Using crypto

Here's the update with crypto.getRandomValues() in place:

JavaScript

function shuffleWithCrypto(array) {
  for (let i = array.length - 1; i >= 1; i--) {
    const r = new Uint32Array(1);
    crypto.getRandomValues(r);
    const j = r[0] % i;
    [array[i], array[j]] = [array[j], array[i]];
  }
}

JavaScript

const items = ["alfa", "bravo", "charlie", "delta", "echo"];
shuffleWithCrypto(items);
const cryptoRandomOutput = document.querySelector("#cryptoRandomOutput");
cryptoRandomOutput.innerHTML = items.join(" - ");

crypto.getRandomValues() Output

The Little Differences

Frankly, I don't know if there will be a perceptual difference between it and Math.random(). It's hard to argue against better randomness when randomness is what you're looking for, though.

-a

end of line

Endnotes

These functions modify the existing array directly.

There is an impact on performance switching to crypto.getRandomValues(). It's ~25x slower on my machine. For example, here's the times it takes to shuffle an array with 1,000,000 items in it:

Math.random()    crypto.getRandomValues()

22ms             620ms
20ms             668ms
20ms             627ms
19ms             620ms
21ms             613ms
24ms             610ms
20ms             623ms
22ms             622ms
21ms             621ms
23ms             618ms
Avg: 21.2ms      Avg: 624.2ms

But, that's a million items. I've never used an array that big in JavaScript. If you cut the array about to 1,000 items the times drop to an avg of 1.4ms.

Sure, it's slower. For my use cases, the difference is imperceptible. I'm unconcerned with the impact.

Footnotes

Designed to make it easier for folks to make stuff for the web.

Jumble with confidence.

The MDN page lists crypto.getRandomValues() as being widely available since 2015. I expect it's been around longer than that in some engines.

crypto.getRandomValues() is very different approach to getting a random number. You create an array with a single slot, fill that slot via a .getRandomValues() call then divide that number and pull the remainder. It's a couple extra lines, but I never see it get used. I expect a big part of that is that the top Stack Overflow answers use Math.random().

It's "go with what you know" syndrome.

A problem with the potential to get worse the more folks use AI. With so many examples using Math.random(), the AI stats modules seem unlikely to provide the update. Generated code and examples will use the old version as a result. That'll further push the new version down the model.

Rinse, repeat.