To get a random item from an array in JavaScript, index it with a floored random multiple of its length:
const fruits = ["apple", "banana", "cherry", "date"];
const pick = fruits[Math.floor(Math.random() * fruits.length)];Math.random() returns a float in the range 0 (inclusive) to 1 (exclusive). Multiply by length, floor it, and you have a valid index from 0 to length - 1. Because Math.random() never returns exactly 1, you can never overshoot the last index, so there is no off-by-one to guard against. That one line is the whole answer for the common case. The rest of this page is the helper worth keeping, the shuffle the search results keep getting wrong, and the one situation where Math.random() is the wrong tool entirely.
Factor it into a helper
You will reach for this often enough that a named helper beats re-typing the expression and miscounting parentheses:
const teSample = (arr) => arr[Math.floor(Math.random() * arr.length)];
teSample(["heads", "tails"]); // "heads" or "tails"Call it teSample (Lodash named the same operation _.sample, so the term is familiar). On an empty array it returns undefined, which is the sensible result. If you need n distinct random items rather than one, do not call teSample in a loop: that can return duplicates. Shuffle the array and take a slice, which brings us to the part most code on the web gets wrong.
Shuffle an array correctly: Fisher-Yates
The shuffle you will see pasted into a hundred answers looks clever and is broken:
// WRONG: biased, do not use
const bad = arr.sort(() => Math.random() - 0.5);It is biased. The comparator returns a random sign each time it is called, but Array.prototype.sort does not call it a uniform number of times per element, and the result is that some orderings come up far more often than others. Run that sort a million times over a small array and tally which value lands in position 0: with a correct shuffle each value should appear there equally often, but the random-comparator version skews hard toward leaving elements near where they started. It is not "random enough," it is wrong.
The correct shuffle is Fisher-Yates (the modern Durstenfeld form): walk the array from the end, and for each position swap it with a randomly chosen earlier-or-equal position.
const teShuffle = (arr) => {
const out = [...arr]; // copy so the original is untouched
for (let i = out.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[out[i], out[j]] = [out[j], out[i]];
}
return out;
};This runs in O(n), touches each element once, and produces every permutation with equal probability. Note the i + 1: each element must be allowed to swap with itself (stay put), and getting that bound wrong reintroduces bias. Returning a copy rather than mutating in place is a personal preference; mutating arr directly is fine if the caller expects it, but copying avoids the surprise of a sort-style in-place side effect. To draw n distinct items, shuffle then slice: teShuffle(arr).slice(0, n).
When Math.random is the wrong tool
Math.random() is a pseudo-random generator. It is fast and fine for shuffling a UI carousel or picking a random tip, but its output is not cryptographically secure: per MDN, the values must not be used for anything security-related, because a determined observer can predict them. If the pick must be unguessable, a password reset token, a session ID, a raffle where someone has an incentive to game it, a shuffled deck in a real-money game, use the Web Crypto API instead:
// Cryptographically secure random index
const teSecureSample = (arr) => {
const buf = new Uint32Array(1);
crypto.getRandomValues(buf);
return arr[buf[0] % arr.length];
};crypto.getRandomValues() fills a typed array with cryptographically strong random values and is available in browsers and in Node.js (as globalThis.crypto). One caveat: the % arr.length above introduces a small modulo bias when arr.length does not evenly divide 2^32. For most array sizes it is negligible, but if you need a provably uniform secure pick, use rejection sampling (discard values in the unusable top slice of the range and draw again) rather than a bare modulo. For shuffling, swap the Math.random() line inside teShuffle for a crypto.getRandomValues-backed index the same way.
The decision is simple: cosmetic randomness, Math.random(); anything an adversary benefits from predicting, crypto.getRandomValues().
Quick reference
| Task | Code |
|---|---|
| Random item | arr[Math.floor(Math.random() * arr.length)] |
| Helper | const teSample = (a) => a[Math.floor(Math.random() * a.length)] |
| Shuffle (correct) | Fisher-Yates: swap each i with random j in 0..i |
| Shuffle (wrong) | arr.sort(() => Math.random() - 0.5) is biased |
| n distinct items | teShuffle(arr).slice(0, n) |
| Unguessable pick | crypto.getRandomValues(new Uint32Array(1)) |
If you are still building the array these operate on, fill an array with default or computed values covers the setup side, and the JavaScript array methods reference is the map of map, filter, slice, and the rest you will combine with these.
FAQ
See also
- Fill a JavaScript array with values: build the array first, then sample or shuffle it.
- JavaScript array methods reference:
map,filter,slice, and the rest you will pair with these. - Generate a UUID in JavaScript: when you need a unique identifier rather than a random pick, and the crypto-backed way to do it.
Sources
Authoritative references this article was fact-checked against.
- Math.random() — MDN referencedeveloper.mozilla.org
- Crypto.getRandomValues() — MDN referencedeveloper.mozilla.org
- Fisher-Yates shuffle (algorithm reference)en.wikipedia.org





