Проверьте, является ли значение объектом в JavaScript - PullRequest
1087 голосов
/ 15 декабря 2011

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

Ответы [ 38 ]

1287 голосов
/ 15 декабря 2011

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

489 голосов
/ 18 марта 2014

Давайте определим «объект» в 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({})
432 голосов
/ 15 декабря 2011

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

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

247 голосов
/ 05 февраля 2013

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

// Is a given variable an object?
_.isObject = function(obj) {
  return obj === Object(obj);
};

ОБНОВЛЕНИЕ

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

// Is a given variable an object?
_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};
167 голосов
/ 13 ноября 2012

Object.prototype.toString.call(myVar) вернет:

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

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

90 голосов
/ 17 мая 2013

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

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
71 голосов
/ 08 сентября 2014

Мне нравится просто:

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

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

ДОКУМЕНТЫ:

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

69 голосов
/ 10 октября 2017

С функцией 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! И это работает для всех ранее описанных тестовых случаев! ?

28 голосов
/ 15 февраля 2017

Хорошо, давайте сначала дадим вам эту концепцию, прежде чем ответить на ваш вопрос, в JavaScript Функции это Object, также null, Object, Arrays и даже Date, так что, как вы видите, not простой способ, подобный typeof obj === 'object', поэтому все упомянутое выше вернет true , но есть способы проверить это с помощью написания функции или использования 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);
22 голосов
/ 19 января 2016

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

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

Это исключает примитивы (простые числа / NaN / Infinity, простые строки, символы, true / false, undefined и null), но должно возвращать true для всего остального (включая 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...