sort.cny.shStart a race
Back to library
04Under the hood

What do libraries actually run?

One-liner sort APIs look different from the outside — under the hood almost every modern JS sort call ends up in the same place. Here's the map.

A caveat. We can't actually watchthese libraries sort bar-by-bar — they hand the work to the engine's internal C++ and only surface a finished array. So we visualize the underlying algorithm they delegate to, and describe the delegation path.

01

Array.prototype.sort

Visualize →

The built-in sort on every JavaScript engine.

arr.sort((a, b) => a - b)
Delegates toTimSort (V8, ≥ 2018)
  • V8 switched from an unstable QuickSort to TimSort in Chrome 70 (Oct 2018).
  • SpiderMonkey (Firefox) has used a stable MergeSort-family sort for years.
  • JavaScriptCore (Safari) uses a merge-based algorithm as well.
  • Since ES2019 the spec itself requires stability.
02

lodash — _.sortBy / _.orderBy

Visualize →

Stable sort-by-key helper. Hands the compare off to the native sort.

_.sortBy(arr, x => x)
Delegates toTimSort (via Array.prototype.sort)
  • Implementation extracts the sort key, calls a comparator-based sort, then unwraps.
  • The actual ordering work is done by the engine's native sort — TimSort in V8.
  • `_.orderBy` adds per-key ascending/descending flags on top of the same machinery.
03

Ramda — R.sort

Visualize →

Curried functional wrapper around the native sort.

R.sort((a, b) => a - b, arr)
Delegates toTimSort (via Array.prototype.sort)
  • R.sort copies the input and calls `Array.prototype.sort` on the clone — pure, but not a new algorithm.
  • So the time complexity and stability characteristics match the engine.
04

Underscore — _.sortBy

Visualize →

The classic predecessor to lodash.

_.sortBy(arr, x => x)
Delegates toTimSort (via Array.prototype.sort)
  • Like lodash: decorate-sort-undecorate pattern around the native sort.
  • Stability is inherited from the engine — since ES2019 guaranteed everywhere.