Проверьте, является ли значение объектом в JavaScript

1366

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

Дэнни Фокс
источник
4
Переменная является переменной. Это может относиться к объекту. Кроме того, вы можете определить «объект» - как показывают ответы и комментарии, существуют различные противоречивые определения (например, nullявляется ли объект).
8
OP, IMO, вы должны принять ответ @ Daan, так как это лучшее решение и должны быть перечислены над другими ответами, чтобы его видели первыми. (Не в обиду другим, у которых тоже есть хорошие ответы.)
Тиффон
2
ИМХО, это действительно зависит от того, что вы (тот, кто ищет ответ на этот вопрос) рассматривает объект, и почему вы проверяете его. Этот вопрос дает разные ответы, если вы пытаетесь отличить массивы (которые являются объектами) от других объектов или если вы пытаетесь отделить скалярные значения от «векторов». И независимо от того , следует ли исключить значение null (то есть Object, согласно typeof) или Functions (то есть Objects), это действительно зависит от того, почему вы проверяете его. Вот почему существует так много ответов, и большинство из них, в контексте, являются правильными.
FrancescoMM
const isEmpty = thing => {typeof thing === "Объект"? ! вещь || ! Object.keys (thing) .length:! Thing && thing! == 0};
Mayur S
1
Было бы здорово, если бы вы могли начать с того, что именно вы подразумеваете под «объектом». (Или, прямо скажем, что часть ответа, который вы ищете, состоит в том, чтобы закрепить различные популярные значения «является объектом», а затем провести различие между ними.) Не имея этого, все говорят друг за другом.
Дон Хэтч

Ответы:

520

ОБНОВЛЕНИЕ :

Этот ответ неполон и дает вводящие в заблуждение результаты . Например, nullтакже считается тип objectв JavaScript, не говоря уже о нескольких других крайних случаях. Следуйте приведенной ниже рекомендации и перейдите к другому «наиболее одобренному (и правильному!) Ответу» .


Оригинальный ответ :

Попробуйте использовать typeof(var)и / или var instanceof something.

РЕДАКТИРОВАТЬ: Этот ответ дает представление о том, как исследовать свойства переменной, но это не пуленепробиваемый рецепт (ведь рецепта нет вообще!) Для проверки, является ли это объект, вдали от него. Поскольку люди, как правило, ищут что-то для копирования, не проводя никаких исследований, я настоятельно рекомендую обратиться к другому, наиболее одобренному (и правильному!) Ответу.

Михаил Крелин - хакер
источник
208
typeofявляется оператором, поэтому нет необходимости ().
Йоши
67
Да, нет необходимости. Я просто предпочитаю это так.
Майкл Крелин - хакер
150
@ MichaelKrelin-хакер: К сожалению, это сбивает с толку людей .
RightSaidFred
11
@RightSaidFred, у меня нет объяснения этому, но я абсолютно не склонен добавлять дополнительные скобки в эти выражения :)
Майкл Крелин - хакер
117
Этот ответ неверен. typeofвозвращает «объект» для нуля, который не является объектом и instanceofне работает для объектов, созданных с использованием Object.create(null).
Николай
1637

Если typeof yourVariable === 'object'это объект или ноль. Если вы хотите исключить ноль, просто сделайте это typeof yourVariable === 'object' && yourVariable !== null.

цыпленок
источник
31
Функции также являются объектами и должны быть включены в ваш чек.
JS_Riddler
4
В этом случае будет yourVariable !== nullлучше практиковаться?
hippietrail
9
@RightSaidFred Кажется, что typeof null == 'object'не будет исправлено в ES6 . Они сказали:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
Константин Смолянин
2
@ Орион, простой ответ - массивы считаются объектами. Чтобы получить более подробный ответ, вам нужно прочитать об этом, typeofпоскольку в нем есть несколько особых случаев, которые не обязательно имеют смысл. Если вы пытаетесь провести различие между массивами и объектами, которые не являются массивами, то вы определенно не хотите их использовать typeof.
Мэтт Фенвик
8
@Tresdin Лучший способ - бегать Object.prototype.toString.call(yourVar), будучи вашим, что нужно проверять. В случае массивов Object.prototype.toString.call([1,2])возвращается[object Array]
Хосе Руи Сантос
539

Давайте определим «объект» в Javascript . Согласно документам MDN , каждое значение является либо объектом, либо примитивом:

примитивная, примитивная ценность

Данные, которые не являются объектом и не имеют никаких методов. JavaScript имеет 5 примитивных типов данных: строка, число, логическое значение, ноль, неопределенный.

Что за примитив?

  • 3
  • 'abc'
  • true
  • null
  • undefined

Что за объект (то есть не примитив)?

  • Object.prototype
  • все произошло от Object.prototype
    • Function.prototype
      • Object
      • Function
      • function C(){} - пользовательские функции
    • C.prototype- свойство prototype пользовательской функции: это не C s prototype
      • new C() - «новая» - определяемая пользователем функция
    • Math
    • Array.prototype
      • массивы
    • {"a": 1, "b": 2} - объекты, созданные с использованием буквенной нотации
    • new Number(3) - обертки вокруг примитивов
    • ... много других вещей ...
  • Object.create(null)
  • все произошло от Object.create(null)

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

instanceof само по себе не сработает, потому что пропускает два случая:

// oops:  isObject(Object.prototype) -> false
// oops:  isObject(Object.create(null)) -> false
function isObject(val) {
    return val instanceof Object; 
}

typeof x === 'object'не будет работать из-за ложных срабатываний ( null) и ложных срабатываний (функций):

// oops: isObject(Object) -> false
function isObject(val) {
    return (typeof val === 'object');
}

Object.prototype.toString.call не сработает из-за ложных срабатываний для всех примитивов:

> Object.prototype.toString.call(3)
"[object Number]"

> Object.prototype.toString.call(new Number(3))
"[object Number]"

Поэтому я использую:

function isObject(val) {
    if (val === null) { return false;}
    return ( (typeof val === 'function') || (typeof val === 'object') );
}

Ответ @ Даана также, кажется, работает:

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

потому что, согласно документам MDN :

Конструктор Object создает объектную оболочку для данного значения. Если значение равно нулю или не определено, он создаст и вернет пустой объект, в противном случае он вернет объект типа, соответствующего данному значению. Если значение уже является объектом, оно вернет значение.


Третий способ, который, кажется, работает (не уверен, что он равен 100%) - использовать метод, Object.getPrototypeOfкоторый выдает исключение, если его аргумент не является объектом:

// these 5 examples throw exceptions
Object.getPrototypeOf(null)
Object.getPrototypeOf(undefined)
Object.getPrototypeOf(3)
Object.getPrototypeOf('abc')
Object.getPrototypeOf(true)

// these 5 examples don't throw exceptions
Object.getPrototypeOf(Object)
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf(Object.create(null))
Object.getPrototypeOf([])
Object.getPrototypeOf({})
Мэтт Фенвик
источник
22
obj === Object(obj)возвращает trueдля массивов.
Онур Йылдырым
5
var x = []; console.log(x === Object(x)); // return true
Иллюминатор
6
Массивы @Illuminator - это объекты в Javascript, как я уже упоминал в своем ответе.
Мэтт Фенвик
1
getPrototypeOfне работает, например, с отозванными прокси, которые являются объектами, но не бросают
Oriol
2
Почему бы не сделать ({}).toString.apply(obj) === '[object Object]'различие между массивами и объектами, которые не являются массивами
MauricioJuanes
295

underscore.js предоставляет следующий метод, чтобы узнать, действительно ли что-то является объектом:

_.isObject = function(obj) {
  return obj === Object(obj);
};

ОБНОВИТЬ

Из-за предыдущей ошибки в V8 и незначительной оптимизации микро-скорости этот метод выглядит следующим образом начиная с underscore.js 1.7.0 (август 2014 г.):

_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};
Даан
источник
57
В javascript массив также является объектом, поэтому большую часть времени вы хотите исключить массив:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Daan
22
почему вы исключаете массив? Это полноценные объекты.
Николай
65
Потому что большую часть времени вы хотите отличить {} от [], например, как входные данные в функции
Daan
5
@Nickolai .. и для перебора вложенных объектов.
Рикки Бойс
6
Отличный ответ. Ручки nullтоже. Должен быть принятый ответ.
Тиффон
180

Object.prototype.toString.call(myVar) вернусь:

  • "[object Object]" если myVar является объектом
  • "[object Array]" если myVar это массив
  • и т.п.

Для получения дополнительной информации об этом и почему это хорошая альтернатива typeof, ознакомьтесь с этой статьей .

Christophe
источник
12
Я недавно узнал, что typeof [] === 'object'-> true. Вот для чего вам нужен этот метод.
Jondlm
3
@Christophe Не различает примитивы и объекты . Object.prototype.toString.call(3)-> "[object Number]". Object.prototype.toString.call(new Number(3))-> "[object Number]"
Мэтт Фенвик
3
@MattFenwick Я не думаю, что это тот «объект», который ОП пытается идентифицировать
Кристоф
3
@ Кристоф, почему ты так думаешь? ИМХО, в отсутствие какого-либо другого определения, данного ОП для «объекта», мне кажется наиболее разумным использовать то, которое используется последовательно в спецификации ECS.
Мэтт Фенвик
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Мистер Поливирл
117

Для простой проверки по объекту или массиву без дополнительного вызова функции (скорость). Как и размещено здесь .

IsArray ()

isArray = function(a) {
    return (!!a) && (a.constructor === Array);
};
console.log(isArray(        )); // false
console.log(isArray(    null)); // false
console.log(isArray(    true)); // false
console.log(isArray(       1)); // false
console.log(isArray(   'str')); // false
console.log(isArray(      {})); // false
console.log(isArray(new Date)); // false
console.log(isArray(      [])); // true

isObject () - Примечание: используйте только для литералов объекта, так как он возвращает false для пользовательских объектов, таких как new Date или new YourCustomObject.

isObject = function(a) {
    return (!!a) && (a.constructor === Object);
};
console.log(isObject(        )); // false
console.log(isObject(    null)); // false
console.log(isObject(    true)); // false
console.log(isObject(       1)); // false
console.log(isObject(   'str')); // false
console.log(isObject(      [])); // false
console.log(isObject(new Date)); // false
console.log(isObject(      {})); // true
Зупа
источник
isObjectработает только с объектными литералами. Если я создаю пользовательский тип, создаю экземпляр типа и проверяю его, он возвращаетfalse
WickyNilliams
3
@zupa: что !! делает?
4
@ 3000 хорошо, если мы пропустим (!! a) часть, она вылетит, потому что null и undefined не имеют конструкторов. (!! а) отфильтровывает их. Это отвечает на ваш вопрос?
zupa
2
@zupa @ 3000 Boolean(a)длиннее, но гораздо более интуитивно понятен. Только не используйте new Boolean(a): ( вот почему )!
JayVee
10
Удивил, лучший ответ так далеко вниз по странице. Это в основном отвечает на вопрос - будет ли это представлено в JSON как нечто, начинающееся с {символа. В случае массива, если вам не нужно поддерживать IE <9, вы можете использовать, Array.isArray()чтобы определить, является ли что-то массивом. Он проходит все предоставленные вами тесты.
Кип
81

Я люблю просто:

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

Если элемент является объектом JS, и это не массив JS, и это не так null... если все три окажутся истинными, верните true. Если какое-либо из этих трех условий не выполнено, &&тест замкнется и falseбудет возвращен. nullТест может быть опущен при желании ( в зависимости от того, как вы используетеnull ).

DOCS:

http://devdocs.io/javascript/operators/typeof

http://devdocs.io/javascript/global_objects/object

http://devdocs.io/javascript/global_objects/array/isarray

http://devdocs.io/javascript/global_objects/null

2540625
источник
3
Как насчет console.log (isObject (new Date ()))? Почему дата должна быть объектом, а не массивом?
Ширрмахер
5
@macher Потому что new Date()возвращает объект. С логической точки зрения массив не является объектом - хотя JavaScript обрабатывает и сообщает о них как таковые. Однако на практике бесполезно видеть их равными, потому что это не так. Например, у объекта нет lengthатрибута и нет методов типа push (). И иногда вы можете захотеть дать функции перегруженные параметры, где вам нужно различать массив или объект, особенно если другие параметры зависят от того, какой из них был задан.
Стэн
1
@StanE Массивы - это определенно объекты. Не знаю , почему вы думаете , объекты не могут иметь lengthсвойство , ни методы , как push, Object.create(Array.prototype)тривиальные контрпример объект , не являющийся массив , который имеет их. Что делает массивы особенными, так это то, что они являются экзотическими объектами с пользовательским [[DefineOwnProperty]] существенным внутренним методом, но они по-прежнему являются объектами.
Ориоль
4
@ Oriol Я не писал, что массивы не являются объектами, и я не писал, что объекты не могут иметь lengthсвойства (я имел в виду, что у литералов объектов lengthпо умолчанию нет атрибутов). Я написал, что массивы не являются объектами с логической точки зрения. Я говорю о программной логике. Иногда необходимо проверить, является ли массив «реальным» массивом и определенно не «реальным» объектом. Вот для чего Array.isArray(). Представьте, что у вас есть функция, которая принимает объект или массив объектов. Проверка на наличие специального атрибута или метода - грязное решение. Родной путь всегда лучше.
Стэн
2
typeof nullэто "object"не "undefined".
2540625
80

С функцией Array.isArray:

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

Без функции Array.isArray:

Просто удивился, сколько откликов за неправильные ответы 😮
Только 1 ответ прошел мои тесты !!! Здесь я создал свою упрощенную версию:

function isObject(o) {
  return o instanceof Object && o.constructor === Object;
}

Как по мне, это понятно и просто, и просто работает! Вот мои тесты:

console.log(isObject({}));             // Will return: true
console.log(isObject([]));             // Will return: false
console.log(isObject(null));           // Will return: false
console.log(isObject(/.*/));           // Will return: false
console.log(isObject(function () {})); // Will return: false

ОДИН БОЛЬШЕ ВРЕМЕНИ: не все ответы проходят этот тест !!! 🙈


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

function isDate(o) {
  return o instanceof Object && o.constructor === Date;
}

простой тест:

var d = new Date();
console.log(isObject(d)); // Will return: false
console.log(isDate(d));   // Will return: true

В результате у вас будет строгий и надежный код!


В случае , если вы не будете создавать такие функции , как isDate, isError, isRegExpи т.д. , вы можете рассмотреть возможность использования этой обобщенной функции:

function isObject(o) {
  return o instanceof Object && typeof o.constructor === 'function';
}

он не будет работать правильно для всех тестовых случаев, упомянутых ранее, но он достаточно хорош для всех объектов (простых или построенных).


isObjectне будет работать в случае Object.create(null)из-за внутренней реализации, Object.createкоторая описана здесь, но вы можете использовать isObjectв более сложной реализации:

function isObject(o, strict = true) {
  if (o === null || o === undefined) {
    return false;
  }
  const instanceOfObject = o instanceof Object;
  const typeOfObject = typeof o === 'object';
  const constructorUndefined = o.constructor === undefined;
  const constructorObject = o.constructor === Object;
  const typeOfConstructorObject = typeof o.constructor === 'function';
  let r;
  if (strict === true) {
    r = (instanceOfObject || typeOfObject) && (constructorUndefined || constructorObject);
  } else {
    r = (constructorUndefined || typeOfConstructorObject);
  }
  return r;
};

На npm v1 уже создан пакет, основанный на этой реализации! И это работает для всех ранее описанных тестовых случаев! 🙂

В. Ковпак
источник
лучший ответ! работает во многих случаях, упомянутых здесь
prieston
Поскольку это возвращает false для isObject (myDateObject), это не ответ на вопрос. Он не сообщает, является ли переменная объектом, только если это объект определенного класса. Вопрос здесь для универсальной функции, которая возвращает true для любого объекта.
Yetanotherjosh
@ Yetanotherjosh Это действительно ответ - вы упомянули случай, который описан в ответе, и смысл - вы должны использовать isDateдля yourDateObject с целью написания надежного кода, иначе у вас будет хрупкий isObjectметод.
В. Ковпак
@VladimirKovpak Использование Dateв моем комментарии было неправильно выбрано, потому что да, ответ действительно обсуждается Date. Но Dateэто только один из бесконечных возможных классов, и точка имеет место для любого другого класса. Пример: class Foo() { }; var x = new Foo(); isObject(x)возвращается false. Я не знаю точно, каков вариант использования OP, но легко представить себе сценарии, в которых необходимость знать обо всех возможных классах и проверять конкретно каждый из них будет невозможна.
Yetanotherjosh
@ Yetanotherjosh Я обновил свой ответ. И добавил еще 1 случай.
В. Ковпак
41

Боже мой! Я думаю, что это может быть короче, чем когда-либо, давайте посмотрим на это:

Короткий и Финальный код

function isObject(obj)
{
    return obj != null && obj.constructor.name === "Object"
}

console.log(isObject({})) // returns true
console.log(isObject([])) // returns false
console.log(isObject(null)) // returns false

Разъяснения

Типы возврата

Тип JavaScript объектов (в том числе null) возвращает"object"

console.log(typeof null, typeof [], typeof {})

Проверка их конструкторов

Проверка их constructorсвойства возвращает функцию с их именами.

console.log(({}).constructor) // returns a function with name "Object"
console.log(([]).constructor) // returns a function with name "Array"
console.log((null).constructor) //throws an error because null does not actually have a property

Представляем Function.name

Function.nameвозвращает только для чтения имя функции или "anonymous"для замыканий.

console.log(({}).constructor.name) // returns "Object"
console.log(([]).constructor.name) // returns "Array"
console.log((null).constructor.name) //throws an error because null does not actually have a property

Примечание. Начиная с 2018 года, имя.функции может не работать в IE. Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility

Эрисан Олашени
источник
3
Мне очень нравится этот, короткий и по существу. Насколько я вижу, он не работает только на 1 вещи. если obj = Object.create(null)и почему вы все равно это сделаете ...?
Джулиан Найт
29

Хорошо, давайте сначала дадим вам эту концепцию, прежде чем ответить на ваш вопрос, в JavaScript функциями являются Object, также null, Object, Arrays и даже Date, поэтому, как вы видите, не существует простого способа, как typeof obj === 'object', поэтому все упомянутое выше вернет истину , но есть способы проверить это с помощью написания функции или использования фреймворков JavaScript, хорошо:

Теперь представьте, что у вас есть настоящий объект (не нуль, не функция или массив):

var obj = {obj1: 'obj1', obj2: 'obj2'};

Чистый JavaScript:

//that's how it gets checked in angular framework
function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

или

//make sure the second object is capitalised 
function isObject(obj) {
   return Object.prototype.toString.call(obj) === '[object Object]';
}

или

function isObject(obj) {
    return obj.constructor.toString().indexOf("Object") > -1;
}

или

function isObject(obj) {
    return obj instanceof Object;
}

Вы можете просто использовать одну из этих функций, как указано выше, в своем коде, вызывая их, и она вернет true, если это объект:

isObject(obj);

Если вы используете JavaScript-фреймворк, они обычно подготовили для вас такие функции, вот некоторые из них:

JQuery:

 //It returns 'object' if real Object;
 jQuery.type(obj);

Угловой:

angular.isObject(obj);

Подчеркни и Лодаш:

//(NOTE: in Underscore and Lodash, functions, arrays return true as well but not null)
_.isObject(obj);
Алиреза
источник
Вы также хотите проверить, что это не массив. так что функция isObject (obj) {вернуть obj! == null && typeof obj === 'object' &&! Array.isArray (obj); }
Matt Goo
Я согласен с вами, но, как вы видите в комментарии, это то, как это делается в angularJ, и я упоминаю об этом в комментарии перед функцией, они считают массив как объект ... посмотрите здесь для получения дополнительной информации: docs .angularjs.org / api / ng / function / angular.isObject
Алиреза,
24

Это зависит от того, что вы имеете в виду под «является объектом». Если вы хотите все, что не является примитивом , то есть вещи, на которые вы можете установить новые свойства, это должно помочь:

function isAnyObject(value) {
    return value != null && (typeof value === 'object' || typeof value === 'function');
}

Это исключает примитивы (простые числа / NaN/ Infinity, простые строки, символы, true/ false, undefinedи null) , но должен возвращать верно для всего остального ( в том числе Number, Booleanи Stringобъектов). Обратите внимание, что JS не определяет, какие "хостовые" объекты, такие как windowили console, должны возвращаться при использовании с ними typeof, поэтому их трудно покрыть такой проверкой.

Если вы хотите узнать, является ли что-то «простым» объектом, то есть оно было создано как литерал {}или с помощью Object.create(null), вы можете сделать это:

function isPlainObject(value) {
    if (Object.prototype.toString.call(value) !== '[object Object]') {
        return false;
    } else {
        var prototype = Object.getPrototypeOf(value);
        return prototype === null || prototype === Object.prototype;
    }
}

Редактировать 2018 : поскольку Symbol.toStringTagтеперь позволяет настраивать выходные данные Object.prototype.toString.call(...), isPlainObjectвышеприведенная функция может возвращаться falseв некоторых случаях, даже если объект начал свою жизнь как литерал. Можно утверждать, что по соглашению объект с пользовательским строковым тегом больше не является простым объектом, но это еще больше запутало определение того, что такое простой объект даже в Javascript.

последний ребенок
источник
Почему typeof === 'function' считается объектом? Функция не объект, не так ли? «new myFunc ()» станет объектом, да, но простой функцией?
Стэн
Нет, каждая функция является объектом в Javascript, независимо от того, как он был создан. Вы можете установить для них свойства (если они не заморожены), они instanceof Objectодинаковы, два одинаковых функциональных литерала не являются строго равными, они передаются по ссылке и т. Д.
последний ребенок
22

Боже мой, слишком много путаницы в других ответах.

Короткий ответ

typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array)

Чтобы проверить это, просто запустите следующие операторы в консоли Chrome.

Дело 1.

var anyVar = {};
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // true

Случай 2

anyVar = [];
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array) // false

Случай 3

anyVar = null;
typeof anyVar == 'object' && anyVar instanceof Object && !(anyVar instanceof Array); // false

объяснение

Хорошо. Давайте разберемся

typeof anyVar == 'object' возвращается три из трех кандидатов - [], {} and null ,

anyVar instanceof Object сужает этих кандидатов до двух - [], {}

!(anyVar instanceof Array) сужается только до одного - {}

Барабанная дробь, пожалуйста!

К этому вы, возможно, уже научились проверять массив в Javascript.

kushalvm
источник
2
Следует отметить, что это также возвращает false(по желанию), когда anyVarявляется функцией.
Джейми Берч
18

Наиболее разумным способом проверки типа значения представляется typeofоператор. Единственная проблема в том, что он ужасно сломан:

  • Возвращает "object"для null, который принадлежит типу Null.
  • Возвращается "function" для вызываемых объектов, которые относятся к типу Object.
  • Он может возвращать (почти) все, что хочет, для нестандартных не вызываемых объектов. Например, IE, похоже, понравилось "unknown". Единственными запрещенными результатами являются "function"и примитивные типы.

typeofнадежен только для не nullпримитивов. Таким образом, способ проверить, является ли значение объектом, - это убедиться, что возвращаемая строка typeofне соответствует примитиву, и что объект не являетсяnull . Однако проблема в том, что будущий стандарт может ввести новый примитивный тип, и наш код будет считать его объектом. Новые типы появляются не часто, но, например, ECMAScript 6 ввел тип Symbol.

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

Полный, но не исчерпывающий список правильных способов проверить, принадлежит ли значение типу Object.

  • Object конструктор

    ObjectКонструктор принуждает переданный аргумент к объекту. Если это уже объект, возвращается тот же объект.

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

    Следующая функция требует ECMAScript 3, который представил ===:

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return Object(value) === value;
    }

    Мне нравится этот подход, потому что он прост и информативен, и аналогичная проверка также будет работать для логических значений, чисел и строк. Тем не менее, имейте в виду, что он зависит от того, что глобальный Objectмир не скрывается и не изменяется.

  • Конструкторы

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

    Следующая функция требует ECMAScript 3, который позволял конструкторам возвращать не-объекты. До ECMAScript 3 это вызвало ошибку, но тогда tryеще не было операторов.

    function isObject(value) { /* Requires ECMAScript 3 or later */
      return new function() { return value; }() === value;
    }

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

  • this ценность

    Старые спецификации ECMAScript требовали, чтобы thisзначение было объектом. Введен ECMAScript 3 Function.prototype.call, который позволяет вызывать функцию с произвольным thisзначением, но принудительно вызывать объект.

    ECMAScript 5 ввел строгий режим, который убрал это поведение, но в небрежном режиме мы все еще можем (но, возможно, не должны) полагаться на него.

    function isObject(value) { /* Requires ECMAScript 3 or later in sloppy mode */
      return function() { return this === value; }.call(value);
    }
  • [[Прототип]]

    Все обычные объекты имеют внутренний слот с именем [[Prototype]], значение которого определяет, от какого другого объекта он наследуется. Значение может быть только объектом или null. Следовательно, вы можете попытаться создать объект, который наследуется от желаемого значения, и проверить, сработало ли оно.

    И то Object.createи другое Object.getPrototypeOfтребует ECMAScript 5.

    function isObject(value) { /* Requires ECMAScript 5 or later */
      try {
        Object.create(value);
        return value !== null;
      } catch(err) {
        return false;
      }
    }
    function isObject(value) { /* Requires ECMAScript 5 or later */
      function Constructor() {}
      Constructor.prototype = value;
      return Object.getPrototypeOf(new Constructor()) === value;
    }
  • Некоторые новые способы ECMAScript 6

    ECMAScript 6 представляет некоторые новые косвенные способы проверки, является ли значение объектом. Они используют ранее замеченный подход, чтобы передать значение некоторому коду, который требует объекта, заключенного в tryоператор для отлова ошибок. Некоторые скрытые примеры, не стоит комментировать


Примечание: я намеренно пропустил некоторые подходы, такие как Object.getPrototypeOf(value)(ES5) и Reflectметоды (ES6), потому что они вызывают важные внутренние методы, которые могут делать неприятные вещи, например, если valueэто прокси. Из соображений безопасности мои примеры приведены только valueбез прямого доступа к нему.

Ориоль
источник
2
«Только мой ответ и ответ Даана полностью верны». немного самонадеянно, учитывая, что я полностью не согласен с вашими первыми двумя предложениями.
zzzzBov
1
@zzzzBov Ну, я посмотрел на все ответы, и они не гарантируют, чтобы всегда возвращали правильный ответ, кроме моего и Даана. Я могу дать воспроизводимые контрпримеры для большинства из них. Другие рекомендуют проверять, возвращает ли typeof «функцию» или «объект», но, как я объяснил, спецификация допускает другие результаты для некоторых объектов. Ответ Мэтта Фенвика содержит тот же правильный ответ, что и ответ Даана, но также содержит неправильные ответы.
Oriol
1
Я не согласен с посылкой, что ваш ответ «совершенно правильный», утверждая, что другие «не гарантируют, что всегда возвращают правильный ответ», никоим образом не опровергает мою позицию. Кроме того, этот вопрос не претендует на то, какой вклад должен давать какой выход.
zzzzBov
1
@zzzzBov Вопрос состоит в том, как проверить, является ли объект объектом. ECMAScript определяет, что такое объект, поэтому я использую это определение. Я не вижу никакой другой разумной интерпретации. Ответы, которые делают другие вещи (например, исключая массивы), могут быть полезны в некоторых обстоятельствах, но они не проверяют, является ли что-то объектом.
Oriol
15

Попробуй это

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}
Talha
источник
15
Почему вы проверяете логические значения?
Jkutianski
5
Это пропускает два случая: Object.prototype instanceof Object-> ложь. Object.create(null) instanceof Object-> ложь.
Мэтт Фенвик
как насчет дат? new Date() instanceof Object => верно
mauron85
13

Готовы использовать функции для проверки

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// Loose equality operator (==) is intentionally used to check
// for undefined too

// Also note that, even null is an object, within isDerivedObject
// function we skip that and always return false for null

объяснение

  • В JavaScript null, Object, Array, Dateи functions являются все объекты. Хотя, nullэто немного надумано. Итак, лучше проверить nullсначала, чтобы обнаружить, что это не нуль.

  • Проверка на typeof o === 'object'гарантии, что oэто объект. Без этой проверки Object.prototype.toStringбыло бы бессмысленно, так как она возвращала бы объект навсегда, даже для undefinedи null! Например: toString(undefined)возвращается [object Undefined]!

    После typeof o === 'object'проверки toString.call (o) является отличным методом, чтобы проверить, oявляется ли объект, производный объект, например Array, Dateили function.

  • В isDerivedObjectфункции он проверяет, oявляется ли функция. Потому что функционируют также как объект, поэтому он здесь. Если этого не произошло, функция вернется как false. Пример: isDerivedObject(function() {})вернется false, однако теперь возвращается true.

  • Всегда можно изменить определение того, что является объектом. Таким образом, можно изменить эти функции соответственно.


тесты

function isObject(o) {
  return null != o && 
    typeof o === 'object' && 
    Object.prototype.toString.call(o) === '[object Object]';
}

function isDerivedObject(o) {
  return !isObject(o) && 
    null != o && 
    (typeof o === 'object' || typeof o === 'function') &&
    /^\[object /.test(Object.prototype.toString.call(o));
}

// TESTS

// is null an object?

console.log(
  'is null an object?', isObject(null)
);

console.log(
  'is null a derived object?', isDerivedObject(null)
);

// is 1234 an object?

console.log(
  'is 1234 an object?', isObject(1234)
);

console.log(
  'is 1234 a derived object?', isDerivedObject(1234)
);

// is new Number(1234) an object?

console.log(
  'is new Number(1234) an object?', isObject(new Number(1234))
);

console.log(
  'is new Number(1234) a derived object?', isDerivedObject(1234)
);

// is function object an object?

console.log(
  'is (new (function (){})) an object?', 
  isObject((new (function (){})))
);

console.log(
  'is (new (function (){})) a derived object?', 
  isObject((new (function (){})))
);

// is {} an object?

console.log(
  'is {} an object?', isObject({})
);

console.log(
  'is {} a derived object?', isDerivedObject({})
);

// is Array an object?

console.log(
  'is Array an object?',
  isObject([])
)

console.log(
  'is Array a derived object?',
  isDerivedObject([])
)

// is Date an object?

console.log(
  'is Date an object?', isObject(new Date())
);

console.log(
  'is Date a derived object?', isDerivedObject(new Date())
);

// is function an object?

console.log(
  'is function an object?', isObject(function(){})
);

console.log(
  'is function a derived object?', isDerivedObject(function(){})
);

Инан Гумус
источник
13

Если вы хотели бы проверить, если prototypeдля objectисключительно исходит от Object. Фильтрует String, Number, Array, Argumentsи т.д.

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

Или как функция стрелки с одним выражением (ES6 +)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'
шаши
источник
1
это лучший способ, но я бы сделал это еще проще на второй строчке:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb
1
Вы также можете снять nullчек, потому чтоObject.prototype.toString.call(null) === '[object Null]'
Gust van de Wal
12
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

var b ={a: 1}
b instanceof Object //true
b instanceof Array //false

var c = null
c instanceof Object //false
c instanceof Array //false

Меня попросили предоставить более подробную информацию. Самый простой и понятный способ проверить, является ли наша переменная объектом typeof myVar. Возвращает строку с типом (например "object","undefined" ).

К сожалению, либо Array и null также имеют тип object. Для получения только реальных объектов необходимо проверить цепочку наследования с помощью instanceofоператора. Это исключит ноль, но Array имеет Object в цепочке наследования.

Итак, решение таково:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}
Kania
источник
/./ instanceof Object //true
yckart
11

Немного поздно ... для "простых объектов" (я имею в виду, например, {'x': 5, 'y': 7}) у меня есть небольшой фрагмент:

function isPlainObject(o) {
   return ((o === null) || Array.isArray(o) || typeof o == 'function') ?
           false
          :(typeof o == 'object');
}

Он генерирует следующий вывод:

console.debug(isPlainObject(isPlainObject)); //function, false
console.debug(isPlainObject({'x': 6, 'y': 16})); //literal object, true
console.debug(isPlainObject(5)); //number, false
console.debug(isPlainObject(undefined)); //undefined, false
console.debug(isPlainObject(null)); //null, false
console.debug(isPlainObject('a')); //string, false
console.debug(isPlainObject([])); //array?, false
console.debug(isPlainObject(true)); //bool, false
console.debug(isPlainObject(false)); //bool, false

Это всегда работает для меня. If будет возвращать «true» только в том случае, если тип «o» равен «объект», но не имеет значения null, массива или функции. :)

Эмилио Гризолиа
источник
Как упоминалось в предыдущих ответах, ваш подход потерпит неудачу в случае объекта Date.
Гжегож Павлик
9

У lodash есть isPlainObject , который может быть тем, что многие ищут на этой странице. Возвращает false, когда дают функцию или массив.

похлопывание
источник
Отлично! Я знал, _.isObjectчто соответствует тому, что JS считает объектом. Но мне обычно нужно различать, например, литерал объекта и массив, что и _.isPlainObjectпозволяет мне делать.
лайм
9

Это будет работать Это функция, которая возвращает истину, ложь или, возможно, ноль.

const isObject = obj => obj && obj.constructor && obj.constructor === Object;

console.log(isObject({})); // true
console.log(isObject([])); // false
console.log(isObject(new Function)); // false
console.log(isObject(new Number(123))); // false
console.log(isObject(null)); // null

pizzarob
источник
2
@SeregPie В будущем вы должны воздерживаться от редактирования кода в ответах. Как этот ответ стоит, при тестировании я получил nullв качестве результата для финального теста, а не false. См. Когда я должен внести изменения в код?
Ник
9

Поскольку кажется, что существует правильное решение этой проблемы, я оставлю свои 2 цента (этот ответ соответствует спецификации и дает правильные результаты при любых обстоятельствах):

Тестирование на примитивы: undefined null boolean string number

function isPrimitive(o){return typeof o!=='object'||null}

Объект не является примитивом:

function isObject(o){return !isPrimitive(o)}

Или в качестве альтернативы:

function isObject(o){return o instanceof Object}
function isPrimitive(o){return !isObject(o)}

Тестирование для любого массива:

const isArray=(function(){
    const arrayTypes=Object.create(null);
    arrayTypes['Array']=true;
    arrayTypes['Int8Array']=true;
    arrayTypes['Uint8Array']=true;
    arrayTypes['Uint8ClampedArray']=true;
    arrayTypes['Int16Array']=true;
    arrayTypes['Uint16Array']=true;
    arrayTypes['Int32Array']=true;
    arrayTypes['Uint32Array']=true;
    arrayTypes['BigInt64Array']=true;
    arrayTypes['BigUint64Array']=true;
    arrayTypes['Float32Array']=true;
    arrayTypes['Float64Array']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!!arrayTypes[o.constructor.name];
    }
}());

Тестирование на объект, исключая: Date RegExp Boolean Number String Functionлюбой массив

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());
c7x43t
источник
8

Когда все остальное терпит неудачу, я использую это:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 
Michal
источник
1
Почему сравнение строк, а не просто item.constructor === Object?
K3 --- rnc
nullвыдает исключениеUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us
@rounce Я стремлюсь поддерживать более старые версии IE, почему это не работает в IE? Из-за indexOfили из-за constructor.name?
Янкапункт
8

Ramda функциональная библиотека имеет замечательную функцию для определения типов JavaScript.

Перефразируя полную функцию :

function type(val) {
  return val === null      ? 'Null'      :
         val === undefined ? 'Undefined' :
         Object.prototype.toString.call(val).slice(8, -1);
}

Мне пришлось смеяться, когда я понял, насколько простым и красивым было решение.

Пример использования из документации Ramda :

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"
DaveGauer
источник
8

После прочтения и попробовать много реализаций, я заметил , что очень немногие люди пытается проверить ценности , как JSON, Math, documentили объекты с цепочкой прототипов более чем на 1 шаг.

Вместо того, чтобы проверять typeofнашу переменную и затем взламывать крайние случаи, я подумал, что было бы лучше, если бы проверка оставалась максимально простой, чтобы избежать необходимости проводить рефакторинг, когда добавляются новые примитивы или собственные объекты, которые регистрируются как typeofобъект ».

В конце концов, typeofоператор скажет вам, является ли что-то объектом JavaScript , но определение объекта в JavaScript слишком широкое для большинства реальных сценариев (например typeof null === 'object'). Ниже приведена функция, которая определяет, vявляется ли переменная объектом, фактически повторяя две проверки:

  1. Цикл начинается , который продолжается до тех пор , пока строковая версией vявляется '[object Object]'.
    Я хотел, чтобы результат функции был точно таким же, как в журналах ниже, так что это единственный критерий «объектности», с которым я закончил. Если это не удается, функция сразу возвращает false.
  2. vзаменяется следующим прототипом в цепочке v = Object.getPrototypeOf(v), но также непосредственно оценивается после. Когда новое значение равно vis null, это означает, что каждый прототип, включая корневой прототип (который вполне мог быть единственным прототипом в цепочке), прошел проверку в цикле while, и мы можем вернуть true. В противном случае начинается новая итерация.

function isObj (v) {
  while (     Object.prototype.toString.call(v) === '[object Object]')
  if    ((v = Object.getPrototypeOf(v))         === null)
  return true
  return false
}

console.log('FALSE:')
console.log('[]                   -> ', isObj([]))
console.log('null                 -> ', isObj(null))
console.log('document             -> ', isObj(document))
console.log('JSON                 -> ', isObj(JSON))
console.log('function             -> ', isObj(function () {}))
console.log('new Date()           -> ', isObj(new Date()))
console.log('RegExp               -> ', isObj(/./))

console.log('TRUE:')
console.log('{}                   -> ', isObj({}))
console.log('new Object()         -> ', isObj(new Object()))
console.log('new Object(null)     -> ', isObj(new Object(null)))
console.log('new Object({})       -> ', isObj(new Object({foo: 'bar'})))
console.log('Object.prototype     -> ', isObj(Object.prototype))
console.log('Object.create(null)  -> ', isObj(Object.create(null)))
console.log('Object.create({})    -> ', isObj(Object.create({foo: 'bar'})))
console.log('deep inheritance     -> ', isObj(Object.create(Object.create({foo: 'bar'}))))

Густ ван де Валь
источник
6
if(typeof value === 'object' && value.constructor === Object)
{
    console.log("This is an object");
}
Махак Чоудхари
источник
1
Если valueэто nullэто вызовет ошибку ...
Гирсам
И конечно это будет falseдля объекта Object.assign({}, {constructor: null}).
user4642212
6

Если явно хотите проверить, является ли данное значение {}.

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}
Carlos
источник
6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!objэто сокращение для проверки, если objэто правда (отфильтровать null)

Айра
источник
6

Это старый вопрос, но мы решили оставить это здесь. Большинство людей проверяют, {}означает ли переменная пару ключ-значение, а не то, что является структурой подчеркивания, которую JavaScript использует для данной вещи, потому что, честно говоря, в основном все в JavaScript является объектом. Так что убираю это с пути. Если вы делаете ...

let x = function() {}
typeof x === 'function' //true
x === Object(x) // true
x = []
x === Object(x) // true

// also
x = null
typeof null // 'object'

В большинстве случаев нам нужно знать, есть ли у нас объект ресурса из API или наш вызов базы данных, возвращенный из ORM. Затем мы можем проверить, не является ли, не является Array, не nullявляется typeof 'function'и является лиObject

// To account also for new Date() as @toddmo pointed out

x instanceof Object && x.constructor === Object

x = 'test' // false
x = 3 // false
x = 45.6 // false
x = undefiend // false
x = 'undefiend' // false
x = null // false
x = function(){} // false
x = [1, 2] // false
x = new Date() // false
x = {} // true
Гилберт
источник
всплывает trueдляnew Date()
toddmo
1
@toddmo спасибо за указание на это. Теперь пример кода возвращает false дляnew Date()
Гилберт
4

Что мне нравится использовать это

function isObject (obj) {
  return typeof(obj) == "object" 
        && !Array.isArray(obj) 
        && obj != null 
        && obj != ""
        && !(obj instanceof String)  }

Я думаю, что в большинстве случаев Дата должна пройти проверку как Объект, поэтому я не фильтрую даты

JohnPan
источник
4

я нашел «новый» способ сделать именно такую ​​проверку типов из этого SO вопроса: почему instanceof возвращает false для некоторых литералов?

Исходя из этого, я создал функцию для проверки типа следующим образом:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return false;         //fallback for null or undefined
    }
}

тогда вы можете просто сделать:

console.log(isVarTypeOf('asdf', String));   // returns true
console.log(isVarTypeOf(new String('asdf'), String));   // returns true
console.log(isVarTypeOf(123, String));   // returns false
console.log(isVarTypeOf(123, Number));   // returns true
console.log(isVarTypeOf(new Date(), String));   // returns false
console.log(isVarTypeOf(new Date(), Number));   // returns false
console.log(isVarTypeOf(new Date(), Date));   // returns true
console.log(isVarTypeOf([], Object));   // returns false
console.log(isVarTypeOf([], Array));   // returns true
console.log(isVarTypeOf({}, Object));   // returns true
console.log(isVarTypeOf({}, Array));   // returns false
console.log(isVarTypeOf(null, Object));   // returns false
console.log(isVarTypeOf(undefined, Object));   // returns false
console.log(isVarTypeOf(false, Boolean));   // returns true

это проверено на Chrome 56, Firefox 52, Microsoft Edge 38, Internet Explorer 11, Opera 43

редактировать:
если вы также хотите проверить, является ли переменная нулевой или неопределенной, вы можете использовать это вместо:

function isVarTypeOf(_var, _type){
    try {
        return _var.constructor === _type;
    } catch(ex) {
        return _var == _type;   //null and undefined are considered the same
        // or you can use === if you want to differentiate them
    }
}

var a = undefined, b = null;
console.log(isVarTypeOf(a, undefined)) // returns true
console.log(isVarTypeOf(b, undefined)) // returns true
console.log(isVarTypeOf(a, null)) // returns true

обновление от комментария Инанка: вызов принят: D

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

function isVarTypeOf(_var, _type, looseCompare){
    if (!looseCompare){
        try {
            return _var.constructor === _type;
        } catch(ex){
            return _var == _type;
        }
    } else {
        try{
            switch(_var.constructor){
                case Number:
                case Function:
                case Boolean:
                case Symbol:
                case Date:
                case String:
                case RegExp:
                    // add all standard objects you want to differentiate here
                    return _var.constructor === _type;
                case Error:
                case EvalError:
                case RangeError:
                case ReferenceError:
                case SyntaxError:
                case TypeError:
                case URIError:
                    // all errors are considered the same when compared to generic Error
                    return (_type === Error ? Error : _var.constructor) === _type;
                case Array:
                case Int8Array:
                case Uint8Array:
                case Uint8ClampedArray:
                case Int16Array:
                case Uint16Array:
                case Int32Array:
                case Uint32Array:
                case Float32Array:
                case Float64Array:
                    // all types of array are considered the same when compared to generic Array
                    return (_type === Array ? Array : _var.constructor) === _type;
                case Object:
                default:
                    // the remaining are considered as custom class/object, so treat it as object when compared to generic Object
                    return (_type === Object ? Object : _var.constructor) === _type;
            }
        } catch(ex){
            return _var == _type;   //null and undefined are considered the same
            // or you can use === if you want to differentiate them
        }
    }
}

таким образом, вы можете сделать так же, как комментарий Inanc:

isVarTypeOf(new (function Foo(){}), Object); // returns false
isVarTypeOf(new (function Foo(){}), Object, true); // returns true

или

Foo = function(){};
Bar = function(){};
isVarTypeOf(new Foo(), Object);   // returns false
isVarTypeOf(new Foo(), Object, true);   // returns true
isVarTypeOf(new Bar(), Foo, true);   // returns false
isVarTypeOf(new Bar(), Bar, true);   // returns true
isVarTypeOf(new Bar(), Bar);    // returns true
am05mhz
источник
Это не может определить, является ли новый класс объектом. isVarTypeOf (new (function Foo () {}), Object) // Это возвращает ложь вместо истины. Смотрите мой ответ ниже для правильной проверки.
Инан Гумус
Тем не менее, вы можете использовать instanceofдля проверки объектов. Тем не менее, это не точная наука.
Инан Гумус
@inanc, так это потому , что new Foo()возвращает Fooобъект, такой же , как new String()возвращает Stringобъект, или new Date()возвращает Dateобъект, вы можете сделать Foo = function(){}; isVarTypeOf(new Foo(), Foo);также
am05mhz
Да, вот что я на самом деле говорю: вы сейчас не проверяете, является ли это объектом.
Inanc Gumus
@inanc Приветствия, я искал способ сделать проверку типов (не просто объект), попал на эту страницу и на другую страницу, потом я был слишком взволнован, что забыл контекст этого вопроса, мой плохой :)
am05mhz