How Lodash _.rest Handles Fewer Arguments
This article explains how the Lodash utility _.rest
processes trailing arguments when a wrapped function is invoked with
fewer arguments than expected. In short, when the number of supplied
arguments does not reach the designated rest parameter index, Lodash
calculates a non-negative length of zero, resulting in an empty array
([]) being passed as the trailing parameter rather than
null or undefined.
The Mechanics of
_.rest
The _.rest method wraps a function so that any arguments
provided from a specified start index onward are collected into a single
trailing array. By default, the start index is derived from the
function's arity, specifically func.length - 1.
When the wrapped function executes, Lodash dynamically determines the size of this rest array by evaluating the total number of passed arguments against the defined start index:
var length = Math.max(args.length - start, 0);Behavior When Arguments Fall Short
If a caller provides fewer arguments than the start
position specifies, args.length - start evaluates to a
negative number. Because of the Math.max(..., 0)
constraint, Lodash safely clamps the length to 0.
From there, the internal logic constructs the rest array:
- Array Allocation: Lodash initializes a new array of
size
0(Array(length)). - Element Population: Since the loop boundary is
determined by
length(which is0), the loop terminates immediately without inserting elements. - Invocation: The original function is invoked with the positional arguments mapped sequentially, followed by the empty array.
Any positional arguments that were defined prior to the rest
parameter but were omitted by the caller simply receive
undefined, consistent with standard JavaScript function
call behavior.
Code Example
Consider a function expecting two regular parameters and a rest parameter:
const _ = require('lodash');
const fn = _.rest(function(a, b, restArgs) {
return { a, b, restArgs };
});
// fn.length is 3, so start defaults to index 2 (the 3rd parameter)
console.log(fn('only-one'));
// Output: { a: 'only-one', b: undefined, restArgs: [] }
console.log(fn());
// Output: { a: undefined, b: undefined, restArgs: [] }Regardless of whether the caller passes zero arguments or just enough
to satisfy some of the positional slots, restArgs is
guaranteed to be an empty array ([]). This design mirrors
native ES6 rest parameters, ensuring predictable array operations like
.map() or .length can be executed on the
trailing parameter without throwing TypeError
exceptions.