Почему в JavaScript нет встроенного метода проверки того, является ли объект простым объектом?

Учитывая развитие JavaScript с момента создания языков, почему нет встроенного метода, который проверяет, является ли объект простым объектом?

Или действительно ли существует метод?

Ответ 1

Не существует явного прямого способа проверить, является ли значение объектом, т.е. относится к типу объекта, но есть некоторые надежные способы сделать это. Я написал список в другом ответе, наиболее кратким кажется

function isObject(value) {
  return Object(value) === value;
}

Подобная функция была запрошена несколько раз на esdiscuss. Например,

Фактически, Object.isObject был предложен как соломенный, и он появился в раннем проекте ES6.

Object.isObject Соломен был в конечном счете отклонен и удален из проекта ES6.

Совсем недавно,

Теперь существует это предложение {tип} Методы, которое включает Object.isObject среди множества других других проверок.

Таким образом, есть еще надежда, и в итоге у нас может быть что-то вроде этого.


Вышеупомянутое предназначено для тестирования объектов в целом. Если вы не хотите, чтобы вы определили, что для вас означает "простой объект".

Например, вы можете проверить свойство constructor. Но любой объект может его настроить.

Вы можете использовать Object.prototype.toString, чтобы получить устаревший ES5 [[Класс]]. Но любой объект может настроить это через Symbol.toStringTag.

Вы можете проверить значение, возвращаемое [[GetPrototypeOf]]. Но даже экзотические объекты могут позволить их прототип быть изменен на любой произвольный объект или нуль. И объекты Proxy даже имеют полный контроль над этим внутренним методом.

Поэтому, скорее всего, вы не сможете положиться на эти тесты. И добавить что-то к стандарту может быть сложно, потому что разные люди могут хотеть разные вещи.

Что бы я хотел, это какой-то способ проверить, является ли объект обычным. То есть, он имеет поведение по умолчанию для основных внутренних методов, которые должны поддерживаться всеми объектами.

Как только вы узнаете, что объект обычный, вы можете полагаться на такие вещи, как [[GetPrototypeOf]], чтобы настроить тест на ваши вкусы.

Ответ 2

Вы можете проверить тип и экземпляр объекта таким образом:

var a = new Date();
console.log(typeof a);
console.log(a instanceof Date);

var b = "Hello";
console.log(typeof b);
console.log(b instanceof Date);

Ответ 3

Полагаясь на [object Object] строковое представление неточно. Это поведение может быть изменено для любых объектов с помощью:

let o = { toString: () => '...' };
('' + o) !== '[object Object]'

var a = [];
a.toString = () => '[object Object]';
('' + a) === '[object Object]';

Самый надежный способ проверить, является ли значение простым объектом,

let o = {}
Object.getPrototypeOf(o) === Object.prototype

И учитывая, что свойство constructor не было подделано, самый простой способ проверить, является ли значение простым объектом,

let o = {}
o.constructor === Object

Это охватывает все POJO, построенные из Object, и не охватывает Object.create(null, { ... }) или любые дочерние классы (включая встроенные элементы типа RegExp или Array):

Object.create(null).constructor !== Object
[].constructor !== Object
(new class {}).constructor !== Object

Одна из возможных причин, по которым нет специального метода проверки на предметность объекта, заключается в том, что ограничение использования только объектов {} нецелесообразно. Это имеет мало смысла в контексте JS. Это предотвращает использование экземпляров класса или относительно "простых" объектов (Object.create({}, ...)).

Для этого потребуется взломать, чтобы нужные объекты, не имеющие равных объектов, прошли проверку:

Object.assign({}, (new class {})).constructor === Object

В большинстве случаев проверка объекта "все, что не запрещено, разрешено", принцип окупается (с особой осторожностью относительно печально известной null несогласованности).

Применяя приведенное выше к этому случаю, безопасное и сжатое условие для фильтрации объектов без массива -

o && typeof o === 'object' && !Array.isArray(o)

И условие для фильтрации объектов, которые не являются встроенными (функции Array, RegExp и т.д.),

o && (o.constructor === Object || !/\[native code\]/.test(o.constructor))

Ответ 4

Всякая JavaScript - это объект, поэтому нет необходимости иметь isObject api