How Lodash toArray Converts Iterables to Arrays
This article explores how Lodash’s _.toArray utility
converts various data structures—including iterables, array-like
objects, strings, and plain objects—into pure JavaScript arrays. You
will learn about the internal type-checking mechanisms Lodash applies,
how it resolves values from different input types, how it handles
complex Unicode characters, and how its behavior compares to native
modern JavaScript features like Array.from.
Understanding the Role of
_.toArray
In JavaScript, several structures resemble arrays or can be looped
over sequentially, but they lack native array prototype methods such as
.map(), .filter(), or .reduce().
These structures include the arguments object, DOM
NodeList collections, Set, Map,
strings, and standard key-value objects.
The _.toArray method provides a reliable,
cross-environment way to transform any of these collections into an
independent, flat, native array (Array).
Step-by-Step: The Internal Conversion Process
Lodash processes the target value through a sequence of condition checks to determine the most efficient extraction strategy:
1. Falsy and Nullish Checking
If the input value is null, undefined, or
falsey (aside from values that can be coerced, like numeric zero),
_.toArray immediately returns a new, empty array
[]. This prevents runtime TypeError exceptions
commonly encountered with native operations.
2. Native Array Fast-Path
If the input is already a native array, Lodash does not simply return
the reference. It performs a shallow copy of the array (equivalent to
array.slice()) to ensure that mutations to the returned
array do not modify the original data source.
3. Iterables and
Symbol.iterator
For modern ES6 iterables—such as Set, Map,
or custom iterables implementing the [Symbol.iterator]
protocol:
- Iterables in General: Lodash invokes the iterable's iterator mechanism, pulling elements sequentially into a new array.
- Maps: When a
Mapis passed, it extracts the map's values (equivalent toArray.from(map.values())), rather than the key-value pairs. - Sets: It reads each entry and places it into the resulting array in insertion order.
4. Array-Like Objects
An object is classified as "array-like" if it is not a function and
possesses a non-negative integer length property (such as
{ length: 2, 0: 'a', 1: 'b' } or a DOM
NodeList). For these structures, Lodash copies the values
from index 0 up to length - 1 into a new array
structure.
5. String and Unicode Handling
Strings are iterable, but direct indexing or naive splitting fails on
surrogate pairs (such as emojis or complex symbols).
_.toArray checks for symbols with astral code points. If
present, it breaks the string apart using Unicode-aware iteration logic,
guaranteeing that characters composed of multiple code units are
preserved accurately as single elements.
6. Plain Objects
Unlike native conversion methods like Array.from (which
returns an empty array for plain objects without a length
property), Lodash gracefully handles standard key-value objects. If a
non-iterable plain object is passed, _.toArray invokes its
internal equivalent of Object.values(), collecting all
enumerable own-property values into the new array:
const user = { id: 101, role: 'admin' };
_.toArray(user); // Returns: [101, 'admin']_.toArray vs. Native
Array.from
While modern JavaScript offers Array.from() and the
spread operator ([...iterable]), Lodash's
_.toArray differs in several key ways:
- Plain Object Support:
Array.from({ a: 1, b: 2 })returns[], whereas_.toArray({ a: 1, b: 2 })extracts the values[1, 2]. - Null Safety: Passing
nullorundefinedtoArray.fromor[...null]throws aTypeError._.toArray(null)safely yields[]. - Map Normalization: Spreading a
Mapyields an array of[key, value]pairs, while_.toArray(map)automatically flattens it to an array containing only the values.