Как проверить, является ли значение объектом в JavaScript?
Как проверить, является ли значение объектом в JavaScript?
Ответы:
ОБНОВЛЕНИЕ :
Этот ответ неполон и дает вводящие в заблуждение результаты . Например, null
также считается тип object
в JavaScript, не говоря уже о нескольких других крайних случаях. Следуйте приведенной ниже рекомендации и перейдите к другому «наиболее одобренному (и правильному!) Ответу» .
Оригинальный ответ :
Попробуйте использовать typeof(var)
и / или var instanceof something
.
РЕДАКТИРОВАТЬ: Этот ответ дает представление о том, как исследовать свойства переменной, но это не пуленепробиваемый рецепт (ведь рецепта нет вообще!) Для проверки, является ли это объект, вдали от него. Поскольку люди, как правило, ищут что-то для копирования, не проводя никаких исследований, я настоятельно рекомендую обратиться к другому, наиболее одобренному (и правильному!) Ответу.
typeof
является оператором, поэтому нет необходимости ()
.
typeof
возвращает «объект» для нуля, который не является объектом и instanceof
не работает для объектов, созданных с использованием Object.create(null)
.
Если typeof yourVariable === 'object'
это объект или ноль. Если вы хотите исключить ноль, просто сделайте это typeof yourVariable === 'object' && yourVariable !== null
.
yourVariable !== null
лучше практиковаться?
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.
typeof
поскольку в нем есть несколько особых случаев, которые не обязательно имеют смысл. Если вы пытаетесь провести различие между массивами и объектами, которые не являются массивами, то вы определенно не хотите их использовать typeof
.
Object.prototype.toString.call(yourVar)
, будучи вашим, что нужно проверять. В случае массивов Object.prototype.toString.call([1,2])
возвращается[object Array]
Давайте определим «объект» в 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({})
obj === Object(obj)
возвращает true
для массивов.
var x = []; console.log(x === Object(x)); // return true
getPrototypeOf
не работает, например, с отозванными прокси, которые являются объектами, но не бросают
({}).toString.apply(obj) === '[object Object]'
различие между массивами и объектами, которые не являются массивами
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;
};
return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
null
тоже. Должен быть принятый ответ.
Object.prototype.toString.call(myVar)
вернусь:
"[object Object]"
если myVar является объектом"[object Array]"
если myVar это массивДля получения дополнительной информации об этом и почему это хорошая альтернатива typeof, ознакомьтесь с этой статьей .
typeof [] === 'object'
-> true
. Вот для чего вам нужен этот метод.
Object.prototype.toString.call(3)
-> "[object Number]"
. Object.prototype.toString.call(new Number(3))
-> "[object Number]
"
getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Для простой проверки по объекту или массиву без дополнительного вызова функции (скорость). Как и размещено здесь .
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
Boolean(a)
длиннее, но гораздо более интуитивно понятен. Только не используйте new Boolean(a)
: ( вот почему )!
{
символа. В случае массива, если вам не нужно поддерживать IE <9, вы можете использовать, Array.isArray()
чтобы определить, является ли что-то массивом. Он проходит все предоставленные вами тесты.
Я люблю просто:
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
new Date()
возвращает объект. С логической точки зрения массив не является объектом - хотя JavaScript обрабатывает и сообщает о них как таковые. Однако на практике бесполезно видеть их равными, потому что это не так. Например, у объекта нет length
атрибута и нет методов типа push (). И иногда вы можете захотеть дать функции перегруженные параметры, где вам нужно различать массив или объект, особенно если другие параметры зависят от того, какой из них был задан.
length
свойство , ни методы , как push
, Object.create(Array.prototype)
тривиальные контрпример объект , не являющийся массив , который имеет их. Что делает массивы особенными, так это то, что они являются экзотическими объектами с пользовательским [[DefineOwnProperty]] существенным внутренним методом, но они по-прежнему являются объектами.
length
свойства (я имел в виду, что у литералов объектов length
по умолчанию нет атрибутов). Я написал, что массивы не являются объектами с логической точки зрения. Я говорю о программной логике. Иногда необходимо проверить, является ли массив «реальным» массивом и определенно не «реальным» объектом. Вот для чего Array.isArray()
. Представьте, что у вас есть функция, которая принимает объект или массив объектов. Проверка на наличие специального атрибута или метода - грязное решение. Родной путь всегда лучше.
typeof null
это "object"
не "undefined"
.
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 уже создан пакет, основанный на этой реализации! И это работает для всех ранее описанных тестовых случаев! 🙂
isDate
для yourDateObject с целью написания надежного кода, иначе у вас будет хрупкий isObject
метод.
Date
в моем комментарии было неправильно выбрано, потому что да, ответ действительно обсуждается Date
. Но Date
это только один из бесконечных возможных классов, и точка имеет место для любого другого класса. Пример: class Foo() { }; var x = new Foo(); isObject(x)
возвращается false
. Я не знаю точно, каков вариант использования OP, но легко представить себе сценарии, в которых необходимость знать обо всех возможных классах и проверять конкретно каждый из них будет невозможна.
Боже мой! Я думаю, что это может быть короче, чем когда-либо, давайте посмотрим на это:
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
возвращает только для чтения имя функции или "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
Object.create(null)
и почему вы все равно это сделаете ...?
Хорошо, давайте сначала дадим вам эту концепцию, прежде чем ответить на ваш вопрос, в 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);
Это зависит от того, что вы имеете в виду под «является объектом». Если вы хотите все, что не является примитивом , то есть вещи, на которые вы можете установить новые свойства, это должно помочь:
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.
instanceof Object
одинаковы, два одинаковых функциональных литерала не являются строго равными, они передаются по ссылке и т. Д.
Боже мой, слишком много путаницы в других ответах.
Короткий ответ
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.
false
(по желанию), когда anyVar
является функцией.
Наиболее разумным способом проверки типа значения представляется typeof
оператор. Единственная проблема в том, что он ужасно сломан:
"object"
для null
, который принадлежит типу Null."function"
для вызываемых объектов, которые относятся к типу Object."unknown"
. Единственными запрещенными результатами являются "function"
и примитивные типы.typeof
надежен только для не null
примитивов. Таким образом, способ проверить, является ли значение объектом, - это убедиться, что возвращаемая строка typeof
не соответствует примитиву, и что объект не являетсяnull
. Однако проблема в том, что будущий стандарт может ввести новый примитивный тип, и наш код будет считать его объектом. Новые типы появляются не часто, но, например, ECMAScript 6 ввел тип Symbol.
Поэтому вместо typeof
я рекомендую только подходы, результат которых зависит от того, является ли значение объектом или нет. Следующее намеревается быть
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
без прямого доступа к нему.
Попробуй это
if (objectName instanceof Object == false) {
alert('Not an object');
}
else {
alert('An object');
}
Object.prototype instanceof Object
-> ложь. Object.create(null) instanceof Object
-> ложь.
new Date() instanceof Object
=> верно
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
и function
s являются все объекты. Хотя, 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(){})
);
Если вы хотели бы проверить, если 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]'
return Object.prototype.toString.call(n) === '[object Object]'
null
чек, потому чтоObject.prototype.toString.call(null) === '[object Null]'
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
}
/./ instanceof Object //true
Немного поздно ... для "простых объектов" (я имею в виду, например, {'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, массива или функции. :)
У lodash есть isPlainObject , который может быть тем, что многие ищут на этой странице. Возвращает false, когда дают функцию или массив.
_.isObject
что соответствует тому, что JS считает объектом. Но мне обычно нужно различать, например, литерал объекта и массив, что и _.isPlainObject
позволяет мне делать.
Это будет работать Это функция, которая возвращает истину, ложь или, возможно, ноль.
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
null
в качестве результата для финального теста, а не false
. См. Когда я должен внести изменения в код?
Поскольку кажется, что существует правильное решение этой проблемы, я оставлю свои 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];
}
}());
Когда все остальное терпит неудачу, я использую это:
var isObject = function(item) {
return item.constructor.name === "Object";
};
item.constructor === Object
?
null
выдает исключениеUncaught TypeError: Cannot read property 'constructor' of null(…)
indexOf
или из-за constructor.name
?
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"
После прочтения и попробовать много реализаций, я заметил , что очень немногие люди пытается проверить ценности , как JSON
, Math
, document
или объекты с цепочкой прототипов более чем на 1 шаг.
Вместо того, чтобы проверять typeof
нашу переменную и затем взламывать крайние случаи, я подумал, что было бы лучше, если бы проверка оставалась максимально простой, чтобы избежать необходимости проводить рефакторинг, когда добавляются новые примитивы или собственные объекты, которые регистрируются как typeof
объект ».
В конце концов, typeof
оператор скажет вам, является ли что-то объектом JavaScript , но определение объекта в JavaScript слишком широкое для большинства реальных сценариев (например typeof null === 'object'
). Ниже приведена функция, которая определяет, v
является ли переменная объектом, фактически повторяя две проверки:
v
является '[object Object]'
. v
заменяется следующим прототипом в цепочке v = Object.getPrototypeOf(v)
, но также непосредственно оценивается после. Когда новое значение равно v
is 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'}))))
if(typeof value === 'object' && value.constructor === Object)
{
console.log("This is an object");
}
value
это null
это вызовет ошибку ...
false
для объекта Object.assign({}, {constructor: null})
.
Это старый вопрос, но мы решили оставить это здесь. Большинство людей проверяют, {}
означает ли переменная пару ключ-значение, а не то, что является структурой подчеркивания, которую 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()
new Date()
я нашел «новый» способ сделать именно такую проверку типов из этого 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
instanceof
для проверки объектов. Тем не менее, это не точная наука.
new Foo()
возвращает Foo
объект, такой же , как new String()
возвращает String
объект, или new Date()
возвращает Date
объект, вы можете сделать Foo = function(){}; isVarTypeOf(new Foo(), Foo);
также
null
является ли объект).