Lodash _.first Behavior on Strings

When the Lodash _.first function (an alias for _.head) is invoked on a string instead of an array, it returns the first character of the string. If an empty string is provided, it returns undefined. This article explains how Lodash handles string inputs under the hood, provides code examples, and highlights key edge cases like Unicode surrogate pairs.

How Lodash Handles Strings

In JavaScript, strings are primitive values, but they behave as array-like objects. They possess a .length property and allow zero-indexed character access using bracket notation (e.g., str[0]).

Lodash’s internal implementation of _.head / _.first generally performs a simple check:

function head(array) {
  return (array && array.length) ? array[0] : undefined;
}

Because a string satisfies both array (truthy) and array.length > 0, the function reads index 0 directly from the string.

Code Examples

Standard Non-Empty String

Calling _.first on a standard string returns a single-character string containing the first character:

const _ = require('lodash');

console.log(_.first('hello')); // Output: 'h'
console.log(_.head('world'));  // Output: 'w'

Empty String

If the string is empty, .length evaluates to 0. Consequently, the ternary check fails and returns undefined:

console.log(_.first('')); // Output: undefined

Whitespace Strings

Strings containing only spaces or tabs still have a length greater than zero. The first character will be returned as whitespace:

console.log(_.first('  abc')); // Output: ' '

Unicode and Surrogate Pair Caveat

Because _.first relies on standard JavaScript bracket notation (array[0]), it accesses UTF-16 code units rather than full Unicode code points.

Characters outside the Basic Multilingual Plane (BMP), such as emojis, are represented by surrogate pairs (two 16-bit code units). When _.first is called on such characters, it returns only the first code unit (the high surrogate), resulting in a broken character:

console.log(_.first('🚀 launch')); // Output: '\uD83D' (not '🚀')

To correctly extract full Unicode characters, use native JavaScript string iterators or array destructuring instead (e.g., [...str][0]).