Lodash zipWith Without an Iteratee Function
When the Lodash _.zipWith method is called without a
terminating iteratee function, it gracefully falls back to the default
behavior of _.zip. Rather than throwing a
TypeError or returning undefined, the function
groups elements from the provided arrays based on their shared indices
and returns them as an array of grouped tuples. This article explains
the internal mechanics of how Lodash handles missing iteratees in
_.zipWith, what output you should expect, and how edge
cases behave.
How Lodash Resolves
Arguments in _.zipWith
Under the hood, _.zipWith accepts a variable number of
array arguments followed by an optional iteratee function. Internally,
Lodash inspects the final element in the argument list to determine how
to process the call:
iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;- Type Check: Lodash checks whether the last passed
argument has a type of
'function'. - Extraction: If the last argument is a function, Lodash pops it off the argument list and uses it to combine the grouped elements.
- Fallback: If the last argument is not a function,
Lodash keeps all passed arguments in the collection list and leaves
iterateeasundefined.
The remaining collection of arguments is then delegated to the
internal unzipWith function.
Internal Delegation to
unzipWith
Once the arguments are parsed, unzipWith executes. It
first performs a standard unzip operation across the
provided arrays to group elements by their respective indices:
function unzipWith(array, iteratee) {
if (!(array != null && array.length)) {
return [];
}
var result = unzip(array);
return iteratee == null ? result : arrayMap(result, function(group) {
return apply(iteratee, undefined, group);
});
}Because iteratee is undefined (which
evaluates as iteratee == null), Lodash skips the
arrayMap step entirely. It returns the raw grouped array
produced by unzip.
Code Example
Calling _.zipWith without an iteratee produces the exact
same output as calling _.zip:
const _ = require('lodash');
const letters = ['a', 'b', 'c'];
const numbers = [1, 2, 3];
const booleans = [true, false, true];
// Calling _.zipWith without an iteratee function
const zippedWith = _.zipWith(letters, numbers, booleans);
// Calling _.zip directly
const standardZip = _.zip(letters, numbers, booleans);
console.log(zippedWith);
// Output: [ ['a', 1, true], ['b', 2, false], ['c', 3, true] ]
console.log(_.isEqual(zippedWith, standardZip));
// Output: trueNon-Function Trailing Arguments
If a non-function value—such as an object, string, or number—is passed as the last argument with the intention of it being an iteratee, Lodash treats it as just another array-like data source to be zipped:
- Strings and Arrays: If a string is passed as the
final argument (e.g.,
_.zipWith([1, 2], 'hi')), it will be treated as an array-like iterable and zipped alongside the other collections ([[1, 'h'], [2, 'i']]). - Non-Iterable Values: If numbers, booleans, or plain
objects are passed, Lodash's base grouping logic will treat them as
empty sources, resulting in
undefinedvalues in the corresponding tuple positions.