Как проверить, является ли значение объектом в 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'truenullundefinedЧто за объект (то есть не примитив)?
Object.prototypeObject.prototype
Function.prototype
ObjectFunctionfunction C(){} - пользовательские функцииC.prototype- свойство prototype пользовательской функции: это не C s prototype
new C() - «новая» - определяемая пользователем функцияMathArray.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и 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(){})
);
Если вы хотели бы проверить, если 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), но также непосредственно оценивается после. Когда новое значение равно 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'}))))
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является ли объект).