Як перевірити, чи є значення Об'єктом у JavaScript?
Як перевірити, чи є значення Об'єктом у JavaScript?
Відповіді:
ОНОВЛЕННЯ :
Ця відповідь неповна і дає оманливі результати . Наприклад, null
також розглядається тип object
у JavaScript, не кажучи вже про декілька інших крайніх випадків. Дотримуйтесь рекомендацій, наведених нижче, і перейдіть до іншої "найоціненішої (і правильної!) Відповіді" .
Оригінальна відповідь :
Спробуйте використовувати typeof(var)
та / або var instanceof something
.
EDIT: Ця відповідь дає уявлення про те, як досліджувати властивості змінної, але це не пуленепробивний рецепт (адже рецепту немає взагалі!) Для перевірки, чи є це об'єкт, далеко від нього. Оскільки люди, як правило, шукають щось, щоб скопіювати звідси, не проводячи жодних досліджень, я настійно рекомендую звернутися до іншого, найбільш схваленого (і правильного!) Відповіді.
typeof
є оператором, тому не потрібно ()
.
typeof
повертає "об'єкт" для null, який не є об'єктом, і 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
- властивість прототипу визначеної користувачем функції: це не C
прототип s
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 :
Конструктор об'єктів створює обгортку об'єкта для заданого значення. Якщо значення є нульовим або невизначеним, воно створить і поверне порожній об'єкт, інакше він поверне об'єкт типу, що відповідає заданому значенню. Якщо значення вже є об'єктом, воно поверне значення.
Третій спосіб , який , здається , на роботу (не впевнений , якщо це 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 [] === '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 () - Примітка: використовуйте лише для Object literals, оскільки вона повертає 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
{
характеру. У випадку масиву, поки вам не потрібно підтримувати 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
. Я точно не знаю, що стосується випадків використання ОП, але легко уявити сценарії, в яких потрібно знати про всі можливі класи та спеціально перевіряти їх проти кожного з них .
Боже мій! Я думаю, що це може бути коротше, ніж будь-коли, нехай це побачить:
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
typeof об’єкти 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 рік, функція Function.name може не працювати в IE https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Browser_compatibility
Object.create(null)
і чому б ти це робив так чи інакше ...?
Добре, давайте дамо вам цю концепцію, перш ніж відповісти на ваше запитання, в JavaScript функціями є "Об'єкт", "також об'єкт", "Об'єкт", "Масиви" і навіть дата, так що, як ви бачите, існує не простий спосіб, як 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;
}
Ви можете просто використовувати одну з цих функцій, як описано вище, у своєму коді, зателефонувавши до них, і вона поверне справжнє значення, якщо це об’єкт:
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)
Щоб перевірити це, просто запустіть наступні твердження в хромованій консолі.
Випадок 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
я рекомендую лише підходи, результат яких змінюється залежно від того, є значення об'єктом чи ні. Наступним має бути: a
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);
}
[[Прототип]]
Усі звичайні об'єкти мають внутрішній слот під назвою [[Прототип]], значення якого визначає, від якого іншого об'єкта він успадковується. Значення може бути лише об'єктом або 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
-> false. 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
або a function
.
У isDerivedObject
функції він перевіряє o
наявність функції. Тому що, функціонуйте також об'єктом, тому він там є. Якщо цього не зробити, функція повернеться як хибна. Приклад: 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
оператора. Це усуне нульове значення, але масив має об’єкт у ланцюжку спадкування.
Тож рішення таке:
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
Це завжди працює для мене. Якщо повернеться "true", лише якщо тип "o" є "об'єктом", але немає нуля, або масиву, або функції. :)
lodash має isPlainObject , який може бути тим, що шукають багато хто, хто заходить на цю сторінку. Він повертає помилковим, коли дає функцію чи масив.
_.isObject
що відповідає тому, що JS вважає об’єктом. Але мені зазвичай потрібно розмежувати, наприклад, об'єкт-буквал і масив, саме це _.isPlainObject
дозволяє мені робити.
Це спрацює. Це функція, яка повертає значення true, false або, можливо, нульове.
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
є null
, це означає, що кожен прототип, включаючи кореневий прототип (який цілком міг би бути єдиним прототипом всередині ланцюга), пройшов перевірку в циклі while, і ми можемо повернути справжнє. В іншому випадку починається нова ітерація.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'
і є anObject
// 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()
Я знайшов "новий" спосіб зробити саме такий тип перевірки типу цього питання: Чому 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
оновлення з коментаря inanc: прийнято виклик: 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
є об'єкт).