What PRNG Algorithm Powers Lodash _.random?
The _.random function in the Lodash JavaScript library
does not implement an independent, proprietary pseudo-random number
generator (PRNG). Instead, it acts as an abstraction layer directly over
JavaScript's native Math.random() method, delegating
generation to the host environment's runtime engine. Consequently, the
actual algorithm generating pseudo-randomness in Lodash depends on the
underlying engine—most notably Google's V8, Mozilla's SpiderMonkey, or
WebKit's JavaScriptCore—which predominantly employ modern,
non-cryptographic shift-register algorithms such as
xorshift128+.
Lodash's Internal Implementation
In the Lodash source code (specifically random.js), the
function defines the range and precision requested by the developer,
taking lower, upper, and floating
parameters. To retrieve a random float, it invokes an internal module,
nativeRandom.js, which is defined as:
const nativeRandom = Math.random
export default nativeRandomLodash applies standard linear scaling to map the [0, 1)
range generated by nativeRandom() to the user's requested
minimum and maximum values:
\[\text{value} = \text{lower} + \text{nativeRandom}() \times (\text{upper} - \text{lower})\]
When an integer output is requested, Lodash applies rounding logic
(Math.floor or Math.round) depending on
whether bounds are inclusive.
The Engine-Level PRNG: xorshift128+
Because Lodash relies on Math.random(), the mathematical
driving force is determined by the JavaScript engine executing the
code:
- Google V8 (Node.js, Chrome, Chromium): In 2015, V8 migrated from an older Multiply-With-Carry (MWC1616) implementation to xorshift128+. The xorshift128+ algorithm maintains an internal 128-bit state across two 64-bit unsigned integers. Each step applies bitwise shifts and XOR operations to advance the state, outputting the sum of the state registers.
- Mozilla SpiderMonkey (Firefox): SpiderMonkey also
uses xorshift128+ to power
Math.random(). - WebKit JavaScriptCore (Safari): Safari's engine uses a variant of the xorshift family (such as xoroshiro128+ or a similar 64-bit shift-register design), tailored for fast execution and high statistical randomness.
Algorithmic Characteristics and Limitations
The algorithms of the xorshift family offer distinct operational characteristics:
- Performance: They rely solely on basic CPU instructions (shifts, XORs, and additions), allowing them to execute in single-digit clock cycles.
- Statistical Quality: xorshift128+ passes rigorous statistical suites, including Dieharder and the majority of TestU01's BigCrush test, ensuring a uniform distribution with a period of \(2^{128} - 1\).
- Non-Cryptographic Nature: xorshift128+ is not a Cryptographically Secure Pseudo-Random Number Generator (CSPRNG). Because its internal state consists of only 128 bits and its output directly exposes state transitions, observing a short sequence of outputs allows an attacker to reconstruct the internal seed and predict all future and past numbers.
Applications requiring secure random values—such as token generation,
cryptographic keys, or password resets—should not use Lodash's
_.random. Instead, developers must use native cryptographic
APIs such as crypto.getRandomValues() in browsers or the
crypto.randomBytes() module in Node.js.