Why Lodash _.isObject Returns True for Functions

In JavaScript development, developers often expect an object to mean purely key-value collections, leading to confusion when utility functions behave differently. This article explains why Lodash's _.isObject method evaluates functions as true, detailing the underlying ECMAScript specification, JavaScript's primitive versus reference type model, and the alternative Lodash methods available for more restrictive type checking.

Functions Are Objects in JavaScript

The primary reason _.isObject returns true for a function is that functions in JavaScript are fundamentally objects. Specifically, a function is a "callable object"—a standard JavaScript object equipped with an internal [[Call]] method that allows it to be invoked.

Because functions inherit from Function.prototype, which in turn inherits from Object.prototype, any function is an instance of the Object constructor:

function sampleFunction() {}
console.log(sampleFunction instanceof Object); // true

Functions can have properties and methods assigned to them just like any standard object:

sampleFunction.customProperty = "Hello";
console.log(sampleFunction.customProperty); // "Hello"

ECMAScript Specification and Type Checks

JavaScript divides data into two distinct categories: primitives and objects.

  1. Primitives: string, number, bigint, boolean, symbol, null, and undefined.
  2. Objects: Everything else, including plain objects, arrays, dates, regular expressions, and functions.

While the native typeof operator returns 'function' for callable objects, the ECMAScript language specification classifies functions under the broader Object type.

Lodash adheres strictly to this language-level definition. The internal implementation of _.isObject checks whether a value is not a primitive:

// Simplified representation of Lodash's _.isObject
function isObject(value) {
  const type = typeof value;
  return value != null && (type === 'object' || type === 'function');
}

By design, _.isObject answers the question: Is this value a non-primitive reference type? Because functions are non-primitive, the method returns true.

Alternatives for Strict Type Checking

If your goal is to distinguish plain data structures from functions or arrays, Lodash provides alternative methods tailored to specific use cases: