How Lodash _.lt Performs Less-Than Comparisons

This article provides an overview of the _.lt method in the Lodash JavaScript utility library, explaining its syntax, underlying comparison mechanics, and edge-case behavior. Readers will learn how _.lt processes different data types such as numbers and strings, how it handles coercion and invalid values, and why developers choose it over native operators in functional programming workflows.

Understanding the _.lt Method

The _.lt method in Lodash is a relational comparison utility that checks whether the first argument is strictly less than the second argument. It returns a boolean value: true if value is less than other, and false otherwise.

Syntax

_.lt(value, other)

Comparison Mechanics Under the Hood

Lodash's _.lt fundamentally relies on the native JavaScript abstract relational comparison algorithm (<), but packages it as a standalone function.

1. Numeric Comparisons

When both arguments are numbers, _.lt performs a standard mathematical comparison.

_.lt(1, 3);   // => true
_.lt(5, 2);   // => false
_.lt(4, 4);   // => false

Because _.lt checks for strictly less than, providing two equivalent values always returns false. To check if a value is less than or equal to another, Lodash provides _.lte.

2. String Comparisons

When comparing two strings, _.lt evaluates them lexicographically based on their UTF-16 code unit values.

_.lt('apple', 'banana'); // => true
_.lt('cat', 'car');      // => false
_.lt('10', '2');         // => true (lexicographical: '1' comes before '2')

3. Mixed Types and Type Coercion

JavaScript attempts type coercion during relational comparisons. If one operand is a number and the other is a numeric string, the string is converted to a number.

_.lt('5', 10); // => true (coerces '5' to 5)
_.lt(5, '10'); // => true (coerces '10' to 10)

4. Handling NaN, null, and undefined

If either operand is NaN, or an un-parseable string that resolves to NaN, the native relational comparison evaluates to false. Lodash follows this standard behavior.

_.lt(NaN, 5);          // => false
_.lt(5, NaN);          // => false
_.lt('hello', 5);      // => false (coerces 'hello' to NaN)
_.lt(null, 1);         // => true (null coerces to 0)
_.lt(undefined, 1);    // => false (undefined coerces to NaN)

Why Use _.lt Instead of the Native < Operator?

While the native < operator is sufficient for inline expressions, _.lt is useful in functional programming patterns:

const numbers = [10, 5, 20, 2, 8];

// Using native syntax requires an arrow function
const smallNative = numbers.filter(n => n < 10);

// Using curried Lodash functions allows partial application
const isLessThanTen = _.curryRight(_.lt)(10);
const smallLodash = numbers.filter(isLessThanTen); // => [5, 2, 8]