Avatar ·

Как в JavaScript проверить, является ли переменная объектом?

Всем привет! Я новичок в JavaScript и столкнулся с проблемой при проверке типов данных. Мне нужно написать функцию, которая принимает аргумент и проверяет, является ли он объектом (не массивом, не null, не примитивом). Я пробовал использовать `typeof`, но он возвращает `"object"` для массивов и `null`, что мне не подходит. Вот пример: ```javascript function isObject(value) { return typeof value === 'object'; } console.log(isObject({})); // true — правильно console.log(isObject([])); // true — а должно быть false, это массив console.log(isObject(null)); // true — а должно быть false, null не объект console.log(isObject(function(){})); // false — а это функция, её тоже не нужно считать объектом ``` Пробовал добавить проверку на `Array.isArray()`, но это не решает проблему с `null`. Также читал про `instanceof Object`, но он тоже не работает с `null` и может давать ложные срабатывания для объектов из других фреймов (например, iframe). Подскажите, как правильно и надёжно проверить, что значение — это именно обычный объект (не массив, не функция, не null)? Нужно универсальное решение, которое будет работать во всех современных браузерах и Node.js. <<>>

Проверка на объект: полное решение

Проблема в том, что typeof не различает разные типы объектов и null. Вот надёжный способ проверки:

function isObject(value) {
  return value !== null && typeof value === 'object' && !Array.isArray(value);
}

// Примеры:
console.log(isObject({}));           // true
console.log(isObject({ a: 1 }));     // true
console.log(isObject([]));           // false
console.log(isObject(null));         // false
console.log(isObject(function(){})); // false
console.log(isObject('строка'));     // false
console.log(isObject(42));           // false
console.log(isObject(new Date()));   // true
console.log(isObject(/regex/));      // true

Почему это работает

  • typeof value === 'object' — отсекает все примитивы (числа, строки, булевы, undefined, symbol, bigint) и функции (для них typeof возвращает 'function').
  • value !== null — убирает null, так как typeof null === 'object' из-за исторической ошибки в JavaScript.
  • !Array.isArray(value) — убирает массивы.

Этот метод считается стандартным и используется в продакшн-коде. Он покрывает все обычные случаи: простые объекты, экземпляры классов, встроенные объекты (Date, RegExp, Map, Set).

Более строгий вариант (только "чистые" объекты)

Если нужно проверить, что объект создан именно через {} или new Object() (исключая экземпляры классов и встроенные объекты), используйте Object.prototype.toString:

function isPlainObject(value) {
  return Object.prototype.toString.call(value) === '[object Object]';
}

console.log(isPlainObject({}));           // true
console.log(isPlainObject(new Date()));   // false
console.log(isPlainObject([]));           // false
console.log(isPlainObject(null));         // false

Важные нюансы

  • Iframe и разные контексты: instanceof может не работать, если объект создан в другом фрейме. Наш метод с typeof и Array.isArray работает корректно в таких случаях.
  • Proxy: Для объектов-прокси проверка тоже работает, так как typeof возвращает 'object'.
  • Object.create(null): Объекты, созданные без прототипа (Object.create(null)), проходят проверку как обычные объекты.

Этот подход — золотой стандарт проверки на объект в JavaScript. Он надёжен, лаконичен и покрывает 99% случаев.

<<>>

Альтернативный подход с использованием lodash

Если вы используете библиотеку lodash, у неё есть готовая функция _.isObject(), которая работает именно так, как нужно:

// Установка: npm install lodash
const _ = require('lodash');

console.log(_.isObject({}));           // true
console.log(_.isObject([]));           // false
console.log(_.isObject(null));         // false
console.log(_.isObject(function(){})); // false
console.log(_.isObject(new Date()));   // true

Внутри lodash использует ту же логику: typeof value === 'object' && value !== null, но дополнительно проверяет, что это не функция (так как typeof function === 'function', это не нужно).

Почему это удобно

  • Не нужно писать свою проверку каждый раз.
  • Код становится чище и читаемее.
  • Библиотека обрабатывает все краевые случаи (null, массивы, функции).

Если вы не хотите подключать целую библиотеку ради одной функции, можно скопировать её реализацию (она очень простая) или использовать чистый JavaScript из первого ответа.