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;
  1. Type Check: Lodash checks whether the last passed argument has a type of 'function'.
  2. Extraction: If the last argument is a function, Lodash pops it off the argument list and uses it to combine the grouped elements.
  3. Fallback: If the last argument is not a function, Lodash keeps all passed arguments in the collection list and leaves iteratee as undefined.

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: true

Non-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: