Bubble sort in JavaScript: how it works, code and complexity
How bubble sort works step by step, a tested JavaScript implementation with early exit and a comparator, its time complexity, and how it compares with the built-in sort.
Updated 5 min read

In this article
Bubble sort repeatedly walks through an array, compares each pair of neighbours and swaps them when they are in the wrong order. After each pass the largest remaining value has "bubbled" to the end, so the next pass can stop one place earlier. It takes O(n²) time, which makes it too slow for real data, but it is the usual first sorting algorithm in courses and interviews because it is short, easy to trace by hand and shows the ideas of passes, swaps, stability and early exit.
Tested with Node.js 24.19.0 (V8 13.6). Every result shown in a comment was printed by running the code. The implementation was checked against toSorted() on 2,000 random arrays.
How bubble sort works, pass by pass
Take [5, 1, 4, 2, 8]. In the first pass 5 is compared with 1 and swapped, then with 4 and swapped, then with 2 and swapped, and finally with 8, which is larger, so it stays. Printing the array after each pass of the implementation below:
pass 1: 1 4 2 5 8 | next end 2
pass 2: 1 2 4 5 8 | next end 1
pass 3: 1 2 4 5 8 | next end 0"Next end" is the position of the last swap in that pass. Everything after it is already in its final place, so the next pass only has to go that far. When a pass makes no swaps, the array is sorted and the loop stops.
The textbook version
// The textbook version: n - 1 passes, each one bubbling the largest remaining value to the end.
function bubbleSortBasic(input) {
const items = [...input];
for (let pass = 0; pass < items.length - 1; pass++) {
for (let i = 0; i < items.length - 1 - pass; i++) {
if (items[i] > items[i + 1]) [items[i], items[i + 1]] = [items[i + 1], items[i]];
}
}
return items;
}
console.log(bubbleSortBasic([5, 1, 4, 2, 8])); // [ 1, 2, 4, 5, 8 ]This always makes n − 1 passes, even when the array is already sorted. It is the version most courses show first.
An optimised, reusable version
This version remembers where the last swap happened, stops as soon as a pass makes no swaps, sorts a copy instead of changing the input, and accepts a comparator with the same contract as Array.prototype.sort:
// Sorts a copy in ascending order; compare works like Array.prototype.sort's comparator.
export function bubbleSort(input, compare = (a, b) => (a < b ? -1 : a > b ? 1 : 0)) {
const items = [...input];
let end = items.length - 1;
while (end > 0) {
let lastSwap = 0;
for (let i = 0; i < end; i++) {
if (compare(items[i], items[i + 1]) > 0) {
[items[i], items[i + 1]] = [items[i + 1], items[i]];
lastSwap = i;
}
}
end = lastSwap; // everything after the last swap is already in place; 0 means no swaps, so stop
}
return items;
}bubbleSort([10, 9, 1]); // [ 1, 9, 10 ]
bubbleSort(['pear', 'Apple', 'fig'], (a, b) => a.localeCompare(b)); // [ 'Apple', 'fig', 'pear' ]
const people = [
{ name: 'Ravi', age: 30 }, { name: 'Ana', age: 25 },
{ name: 'Lee', age: 30 }, { name: 'Bo', age: 25 },
];
bubbleSort(people, (a, b) => a.age - b.age).map((p) => p.name);
// [ 'Ana', 'Bo', 'Ravi', 'Lee' ] (equal ages keep their original order: the sort is stable)The default comparator uses < and >, so numbers sort numerically. That differs from the built-in sort(), which without a comparator converts values to strings and puts 10 before 9.
Time and space complexity
| Case | Comparisons | Example (6 items) |
|---|---|---|
| Best: already sorted | O(n), one pass with early exit | 5 comparisons |
| Average | O(n²) | – |
| Worst: reverse order | O(n²), n(n − 1)/2 | 15 comparisons |
We counted the comparisons in the table by running the function. Extra space is O(1) when sorting in place; our version uses O(n) because it copies the input first, which you can remove if changing the array is acceptable. Bubble sort is stable, because it only swaps neighbours that are strictly out of order, so equal items never pass each other.
Bubble sort versus the built-in sort
Sorting random numbers with our function and with toSorted() on Node.js 24.19.0:
| Items | Bubble sort | toSorted((a, b) => a - b) |
|---|---|---|
| 1,000 | 9 ms | 0.6 ms |
| 10,000 | 612 ms | 2.3 ms |
Ten times more data took about 67 times longer with bubble sort, which is what O(n²) means in practice. V8's built-in sort uses TimSort, which is O(n log n) and also stable. In real code, use array.toSorted(compare) to get a sorted copy or array.sort(compare) to sort in place. Bubble sort only makes sense for teaching, for tiny arrays that are almost sorted, or on hardware where code size matters more than speed.
Bubble sort interview questions
- Why can each pass stop one place earlier? Each pass moves the largest remaining value to its final position at the end.
- How do you make it O(n) on sorted input? Track whether a pass swapped anything and stop when it did not.
- Is it stable? Yes, as long as you swap only when the left item is strictly greater.
- How does it compare with insertion sort? Both are O(n²) and stable, but insertion sort usually makes fewer writes and is faster on nearly sorted data, which is why real sort implementations such as TimSort use insertion sort for short runs.
For more questions on arrays, closures and asynchronous code, see our JavaScript interview questions and answers.
Frequently asked questions
What is the time complexity of bubble sort?
O(n²) in the average and worst cases. With an early exit when a pass makes no swaps, the best case, an already sorted array, is O(n). It needs O(1) extra space when it sorts in place.
Is bubble sort stable?
Yes. It only swaps neighbours when the left one is strictly greater, so equal items keep their original order.
Should I use bubble sort in JavaScript?
Not in production code.
array.toSorted(compare)orarray.sort(compare)is O(n log n), stable and far faster. Bubble sort is useful for learning and interviews.Why does [10, 9, 1].sort() return [1, 10, 9]?
Without a comparator,
sort()compares values as strings, and the string "10" comes before "9". Pass(a, b) => a - bto sort numbers.
Your next customer could start right here.
Introduce your tool, product or business to readers exploring technology.
Explore placements and request a private quote
Sources
- Array.prototype.sort() — MDN Web Docs
- Array.prototype.toSorted() — MDN Web Docs
- Getting things sorted in V8 — V8, 2018-09-28
- Bubble sort — Wikipedia
Written with substantial AI assistance. Facts checked against cited sources. Editorial policy.
Comments
No comments yet. Be the first to join the conversation.
Leave a comment
Every comment is read by a moderator before it appears. Your email address is never published; it is used only to contact you about this comment.
More from Cloudsoft Zone

Industry updateJavaScript
tsrs explained: can a Rust port make TypeScript checks 8x faster?
tsrs is an experimental Rust port of the TypeScript compiler from Cloudflare and VoidZero. What the 8x speed and 70% memory claims mean, and how to test it.
By Cloudsoft Zone

TutorialDevOps
Laravel backup restore: recover the application, database and uploaded files together
Plan Laravel backup restore around a recoverable set of code, database, uploaded objects and protected keys, then verify the complete application in isolation.
By Cloudsoft Zone

TutorialDevOps
Laravel S3 compatible uploads: private files, MinIO endpoints and safe delivery
Build Laravel S3 compatible uploads with a private disk, scoped credentials, validated files, unique object keys and authorized downloads across MinIO or S3.
By Cloudsoft Zone
