Перевірте, чи значення є об’єктом у JavaScript


1362

Як перевірити, чи є значення Об'єктом у JavaScript?


4
Змінна - це змінна. Це може стосуватися об'єкта. Також ви можете визначити "об'єкт" - як показують відповіді та коментарі, існують різні суперечливі визначення (наприклад, чи nullє об'єкт).

8
ОП, ІМО, ви повинні прийняти відповідь @ Даана, оскільки це найкраще рішення, і його слід перелічити вище інших відповідей, щоб це було видно першим. (Не ображайтесь на інших, хто також має гарні відповіді.)
tiffon

2
IMHO, це дійсно залежить від того, що ви (той, хто шукає відповіді на це запитання) вважаєте Об'єкт, і чому ви це перевіряєте. Це запитання дає різні відповіді, якщо ви намагаєтесь відрізнити масиви ( це об'єкти) від інших об'єктів або якщо ви намагаєтесь відокремити скалярні значення від "векторів". І є чи нуль (що є об'єктом, в відповідно до TYPEOF) або функції (які є повинні бути виключені об'єкти) чи ні, це дійсно залежить від того, чому ви перевіряєте його. Ось чому відповідей так багато, і більшість з них, в контексті, є правильними.
FrancescoMM

const isEmpty = thing => {typeof thing === "об'єкт"? ! річ || ! Object.keys (річ) .length:! Річ && річ! == 0};
Mayur S

1
Було б чудово, якби ви могли почати з того, що саме ви маєте на увазі під "об'єктом". (Або чітко скажіть, що частина відповіді, яку ви шукаєте, полягає в тому, щоб визначити різні популярні значення "є об'єктом", а потім розмежувати їх.) Відсутній той факт, що всі розмовляють один з одним.
Дон Хетч

Відповіді:


520

ОНОВЛЕННЯ :

Ця відповідь неповна і дає оманливі результати . Наприклад, nullтакож розглядається тип objectу JavaScript, не кажучи вже про декілька інших крайніх випадків. Дотримуйтесь рекомендацій, наведених нижче, і перейдіть до іншої "найоціненішої (і правильної!) Відповіді" .


Оригінальна відповідь :

Спробуйте використовувати typeof(var)та / або var instanceof something.

EDIT: Ця відповідь дає уявлення про те, як досліджувати властивості змінної, але це не пуленепробивний рецепт (адже рецепту немає взагалі!) Для перевірки, чи є це об'єкт, далеко від нього. Оскільки люди, як правило, шукають щось, щоб скопіювати звідси, не проводячи жодних досліджень, я настійно рекомендую звернутися до іншого, найбільш схваленого (і правильного!) Відповіді.


208
typeofє оператором, тому не потрібно ().
Йоші

67
Так, не потрібно. Я просто віддаю перевагу цьому.
Майкл Крелін - хакер

150
@ MichaelKrelin-хакер: Це прикро, оскільки воно бентежить людей .
RightSaidFred

11
@RightSaidFred, у мене немає пояснень, але я абсолютно не схильний додавати додаткові дужки в ці вирази :)
Michael Krelin - хакер

117
Ця відповідь невірна. typeofповертає "об'єкт" для null, який не є об'єктом, і instanceofне працює для об'єктів, створених за допомогою Object.create(null).
Микола

1631

Якщо typeof yourVariable === 'object'це об'єкт або нуль. Якщо ви хочете виключити нуль, просто зробіть це typeof yourVariable === 'object' && yourVariable !== null.


31
Функції також є об'єктами і повинні бути включені у ваш чек.
JS_Riddler

4
У цьому випадку буде yourVariable !== nullкращою практикою?
hippietrail

9
@RightSaidFred Здається, typeof null == 'object'це не буде виправлено в ES6 . Вони сказали:This proposal has been rejected. It was implemented in V8 but it turned out that it broke a lot of existing sites. In the spirit of One JavaScript this is not feasible.
Костянтин Смолянін

2
@Orion проста відповідь полягає в тому, що масиви вважаються об'єктами. Щоб отримати більш детальну відповідь, вам доведеться прочитати далі, typeofоскільки в ньому є кілька особливих випадків, які не обов'язково мають багато сенсу. Якщо ви намагаєтесь розмежовувати масиви та об'єкти, які не є масивами, ви точно не хочете користуватися ними typeof.
Метт Фенвік

8
@Tresdin Найкращим способом є запуск Object.prototype.toString.call(yourVar), будучи вашим вар, що вам потрібно перевірити. У разі масивів, Object.prototype.toString.call([1,2])повертається[object Array]
Хосе Руй Сантос,

537

Давайте визначимо «об’єкт» у 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({})

22
obj === Object(obj)повернення trueдля масивів.
Onur Yıldırım

5
var x = []; console.log(x === Object(x)); // return true
Освітлювач

6
Масиви @Illuminator - це об’єкти в Javascript, про що я згадував у своїй відповіді.
Метт Фенвік

1
getPrototypeOfне працює, наприклад, з відкликаними проксі-серверами, які є об'єктами, але кидають.
Оріол

2
Чому б ({}).toString.apply(obj) === '[object Object]'це не розрізняти масиви та об’єкти, які не є масивами
MauricioJuanes

295

underscore.js надає наступний метод, щоб з’ясувати, чи справді щось є об’єктом:

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

ОНОВЛЕННЯ

Через попередню помилку в V8 та незначну оптимізацію мікрошвидкісних обставин , метод underscore.js 1.7.0 (серпень 2014 року) виглядає наступним чином :

_.isObject = function(obj) {
  var type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

57
У javascript масив також є об'єктом, тому більшу частину часу ви хочете виключити масив:return obj === Object(obj) && Object.prototype.toString.call(obj) !== '[object Array]'
Даан

22
чому б ви виключили масив? Вони є повноцінними об’єктами.
Микола

65
Тому що більшу частину часу ти хочеш відрізнити {} від [], наприклад, як вхід у функцію
Даан

5
@Nickolai ..і для повторення через вкладені об'єкти.
Рікі Бойс

6
Чудова відповідь. Ручки nullтеж. Повинна бути прийнята відповідь.
tiffon

179

Object.prototype.toString.call(myVar) повернеться:

  • "[object Object]" якщо myVar - об’єкт
  • "[object Array]" якщо myVar - це масив
  • тощо.

Для отримання додаткової інформації про це та чому це хороша альтернатива типу, перегляньте цю статтю .


12
Нещодавно я дізнався, що typeof [] === 'object'-> true. Ось для чого вам потрібен цей метод.
Jondlm

3
@Christophe Не розрізняє примітивів та об'єктів . Object.prototype.toString.call(3)-> "[object Number]". Object.prototype.toString.call(new Number(3))-> "[object Number]"
Метт Фенвік

3
@MattFenwick Я не думаю, що це такий "об’єкт", який ОП намагається визначити
Крістоф,

3
@Christophe чому ти вважаєш це? IMHO, за відсутності будь-якого іншого визначення, визначеного ОП для "об'єкта", мені здається найбільш розумним перейти до того, яке послідовно використовується у всіх специфікаціях ECS.
Метт Фенвік

getType=function(obj){return Object.prototype.toString.call(obj).match(/\[object (\w+)\]/)[1];};
Містер Polywhirl

115

Для простої перевірки об'єкта чи масиву без додаткового виклику функції (швидкість). Як також розміщено тут .

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
WickyNilliams

3
@zupa: що !! a робить?

4
@ 3000 добре, якщо ми залишимо частину (!! a), вона вийде з ладу, тому що нульова та невизначена не має конструкторів. (!! a) фільтрує їх. Це відповідає на ваше запитання?
zupa

2
@zupa @ 3000 Boolean(a)довший, але набагато інтуїтивніший. Просто не використовуйте new Boolean(a): ( ось чому )!
JayVee

10
Здивований, що найкраща відповідь поки що внизу сторінки. Це в основному відповідає на питання - чи було б це представлено в JSON як щось, що починається з {характеру. У випадку масиву, поки вам не потрібно підтримувати IE <9, ви можете використовувати, Array.isArray()щоб визначити, чи є щось масивом. Він проходить усі надані вами тестові справи.
Кіп

81

Мені подобається просто:

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

Якщо елемент є об'єктом JS, а це не масив JS, і це не null… якщо всі три виявляться правдивими, поверніться true. Якщо будь-яка з трьох умов не виконана, &&тест завершиться коротким замиканням і falseповернеться. nullТест може бути опущений при бажанні ( в залежності від того, як ви використовуєтеnull ).

DOCS:

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

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

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

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


3
Що щодо console.log (isObject (нова дата ()))? Чому дата повинна бути об’єктом, а масив - ні?
schirrmacher

5
@macher Тому що new Date()повертає об'єкт. Масив з логічної точки зору не є об'єктом, хоча JavaScript обробляє та повідомляє їх як такі. На практиці, однак, не є корисним бачити їх рівними, оскільки вони не є. Об'єкт не має lengthатрибута, наприклад, і у нього немає таких методів, як push (). І іноді ви можете надати функцію перевантажених парам, де потрібно змінити масив або об'єкт, особливо якщо інші параметри залежать від того, який був заданий.
StanE

1
@StanE Масиви - це безумовно об'єкти. Не знаю , чому ви думаєте , об'єкти не можуть мати lengthвластивість , ні методи , як push, Object.create(Array.prototype)тривіальні контрприклад об'єкт , який не є масив , який має їх. Що робить масиви особливими, це те, що вони є екзотичними об'єктами, що мають [[DefineOwnProperty]] власний внутрішній метод, але вони все ще є об'єктами.
Оріол

4
@Oriol Я ні писав, що масиви не є об'єктами, ні я не писав, що об'єкти не можуть мати lengthвластивість (я мав на увазі, що літерали об'єктів не мають lengthатрибутів за замовчуванням). Я писав, що масиви не є об’єктами з логічної точки зору. Я говорю про логіку програми. Іноді потрібно перевірити, чи масив є "реальним" масивом, а точно не "реальним" об'єктом. Ось для чого Array.isArray(). Уявіть, що у вас є функція, яка приймає об'єкт або масив об'єктів. Перевірка спеціального атрибута чи методу - брудне рішення. Рідний спосіб завжди кращий.
StanE

2
typeof nullє "object", ні "undefined".
2540625

80

З функцією Array.isArray:

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

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

Просто здивований, скільки обґрунтованих відповідей за неправильні відповіді 😮
Тільки 1 відповідь пройшла мої тести !!! Тут я створив свою спрощену версію:

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

Як на мене, це зрозуміло і просто, і просто працює! Ось мої тести:

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

ОДИН БОЛЬШ ЧАС: не всі відповіді проходять цей тест !!! 🙈


У випадку, якщо вам потрібно перевірити, що об'єкт є екземпляром певного класу, ви повинні перевірити конструктор з вашим певним класом, наприклад:

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

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

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

Як результат, у вас буде суворий і надійний код!


У разі , якщо ви не будете створювати такі функції , як isDate, isError, isRegExpі т.д. , ви можете розглянути можливість використання цієї узагальненої функції:

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

він не працюватиме правильно для всіх згаданих раніше тестових випадків, але він достатньо хороший для всіх об'єктів (звичайних або побудованих).


isObjectне буде працювати в тому випадку, Object.create(null)якщо внутрішня реалізація цього Object.createпояснюється тут, але ви можете використовувати isObjectв більш досконалій реалізації:

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

На цій реалізації вже створений пакет на npm v1! І це працює для всіх раніше описаних тестових випадків! 🙂


найкраща відповідь! працює для багатьох згаданих тут
священик

Оскільки це повертає помилку для isObject (myDateObject), це не є відповіддю на питання. Він не вказує, чи є змінною об'єкт, лише якщо це об'єкт певного класу. Тут йдеться про загальну функцію, яка повертає істину для будь-якого об'єкта.
Єтатернотеш

@Yetagetherjosh Це дійсно відповідь 🤓 ви згадали випадок, який описаний у відповіді, і суть - вам потрібно використовувати isDateдля yourDateObject з метою написання надійного коду, інакше у вас буде крихкий isObjectметод.
В. Ковпак

@VladimirKovpak Використання Dateв моєму коментарі було обрано неправильно, оскільки так, відповідь все-таки обговорюється Date. Але Dateце лише один з нескінченних можливих класів, і справа стосується будь-якого іншого класу. Приклад: class Foo() { }; var x = new Foo(); isObject(x)повертає false. Я точно не знаю, що стосується випадків використання ОП, але легко уявити сценарії, в яких потрібно знати про всі можливі класи та спеціально перевіряти їх проти кожного з них .
Єтатернотеш

@Yetagetherjosh Я оновив свою відповідь. І додав ще 1 випадок.
В. Ковпак

40

Боже мій! Я думаю, що це може бути коротше, ніж будь-коли, нехай це побачить:

Короткий та заключний код

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

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


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

29

Добре, давайте дамо вам цю концепцію, перш ніж відповісти на ваше запитання, в 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);

Ви також хочете перевірити, що це не масив. тому функція isObject (obj) {return obj! == null && typeof obj === 'object' &&! Array.isArray (obj); }
Метт Гуо

Я згоден з вами, але як ви бачите в коментарі, так це робиться в angularJs, і я згадую це в коментарі перед функцією, вони вважають масив об’єктом ... дивіться тут для отримання додаткової інформації: docs .angularjs.org / api / ng / function / angular.isObject
Alireza

24

Це залежить від того, що ви маєте на увазі під "поняттям". Якщо ви хочете, щоб все, що не є примітивом , тобто речі, на які можна встановити нові властивості, слід виконати фокус:

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

Це виключає примітиви (прості числа / NaN/ Infinity, прості рядки, символи, true/ false, undefinedі null) , але повинен повертати вірно для всього іншого ( в тому числі Number, Booleanі Stringоб'єктів). Зауважте, що JS не визначає, які об'єкти "хост", такі як windowабо console, повинні повертатися при використанніtypeof , тому їх важко прикрити таким чеком.

Якщо ви хочете знати, чи є щось "звичайним" об'єктом, тобто воно було створене як буквальне {}чи з Object.create(null), ви можете зробити це:

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

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


Чому typeof === 'функція' вважається об'єктом? Функція не є об'єктом, чи не так? "new myFunc ()" стане об'єктом, так, але простою функцією?
StanE

Ні, кожна функція є об'єктом у Javascript, незалежно від того, як вона створена. Ви можете встановити на них властивості (якщо вони не заморожені), вони є instanceof Object, два однакові літерали функції не є абсолютно рівними, вони передаються посиланням тощо.
остання дитина

21

Боже мій, занадто багато плутанини в інших відповідях.

Коротка відповідь

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.


2
Зверніть увагу, це також повертається false(за бажанням), коли anyVarце функція.
Джеймі Береза

18

Найбільш розумним способом перевірити тип значення, здається, typeofоператор. Єдина проблема полягає в тому, що вона жахливо зламана:

  • Він повертається "object"заnull , що належить до типу Null.
  • Це повертається "function" для об'єктів, що викликаються, що належать до типу Object.
  • Він може повернути (майже) все, що завгодно, для нестандартних об'єктів, що не викликаються. Наприклад, IE, здавалося, подобається "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без прямого доступу до неї.


2
"Тільки моя відповідь і відповіді Даана цілком правильні". трохи самонадійний, враховуючи, що я цілком не згоден з вашими першими двома реченнями.
zzzzBov

1
@zzzzBov Добре, я переглянув усі відповіді, і вони не гарантують завжди повертати правильну відповідь, крім моєї та Даанової. Я можу дати відтворювані контрприклади більшості з них. Інші рекомендують перевірити, чи typeof повертає "функцію" або "об'єкт", але, як я пояснив, специфікація дозволяє отримати інші результати для деяких об'єктів. Відповідь Метта Фенвіка містить таку ж правильну відповідь, що і Даана, але містить неправильну.
Оріол

1
Я не погоджувався з припущенням про те, що ваша відповідь "цілком правильна", стверджуючи, що інші "не гарантують завжди повертати належну відповідь", жодним чином не спростовує мою позицію. Крім того, питання не пред'являє жодних претензій щодо того, який вхід повинен дати який результат.
zzzzBov

1
@zzzzBov Питання задає питання, як перевірити, чи є щось об’єктом. ECMAScript визначає, що таке об'єкт, тому я використовую це визначення. Я не бачу жодної іншої розумної інтерпретації. Відповіді, які роблять інші речі (як-от виключення масивів), можуть бути корисними за деяких обставин, але вони не перевіряють, чи є щось об’єктом.
Оріол


15

Спробуйте це

if (objectName instanceof Object == false) {
  alert('Not an object');
}
else {
  alert('An object');
}

14
Чому ви добуле перевіряєте булеви?
jkutianski

5
У цьому випадку пропущено два випадки: Object.prototype instanceof Object-> false. Object.create(null) instanceof Object-> хибний.
Метт Фенвік

як щодо дат? new Date() instanceof Object => вірно
mauron85

13

Готові до використання функції для перевірки

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

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

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

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

Пояснення

  • В JavaScript null, Object, Array, Dateі functions є всі об'єкти. Хоча, nullтрохи надуманий. Отже, краще перевірити nullперший, щоб виявити це не нульовим.

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

    Після typeof o === 'object'перевірки, toString.call (o) - чудовий метод перевірити, чи oє об’єкт, похідний об'єкт, як Array, Dateабо 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(){})
);


13

Якщо ви хотіли б перевірити , якщо prototypeдля objectтільки приходить від Object. Фільтрує String, Number, Array, Argumentsі т.д.

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

Або як функція стрілки з одним виразом (ES6 +)

const isObject = n => Object.prototype.toString.call(n) === '[object Object]'

1
це найкращий спосіб, але я б це полегшило ще на другому рядку:return Object.prototype.toString.call(n) === '[object Object]'
mesqueeb

1
Ви також можете зняти nullчек, тому щоObject.prototype.toString.call(null) === '[object Null]'
Gust van de Wal

12
var a = [1]
typeof a //"object"
a instanceof Object //true
a instanceof Array //true

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

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

Мене попросили надати більш детальну інформацію. Найбільш чистий і зрозумілий спосіб перевірити, чи є наша змінна об'єктом typeof myVar. Він повертає рядок з типом (наприклад "object", "undefined").

На жаль, або Array і null також мають тип object. Щоб брати лише реальні об'єкти, потрібно перевірити спадковий ланцюг за допомогою instanceofоператора. Це усуне нульове значення, але масив має об’єкт у ланцюжку спадкування.

Тож рішення таке:

if (myVar instanceof Object && !(myVar instanceof Array)) {
  // code for objects
}

/./ instanceof Object //true
yckart

11

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

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

Він генерує наступний вихід:

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

Це завжди працює для мене. Якщо повернеться "true", лише якщо тип "o" є "об'єктом", але немає нуля, або масиву, або функції. :)


Як було сказано в попередніх відповідях, ваш підхід не вдасться у випадку об'єкта Date.
Grzegorz Pawlik

9

lodash має isPlainObject , який може бути тим, що шукають багато хто, хто заходить на цю сторінку. Він повертає помилковим, коли дає функцію чи масив.


Ідеально! Я знав, _.isObjectщо відповідає тому, що JS вважає об’єктом. Але мені зазвичай потрібно розмежувати, наприклад, об'єкт-буквал і масив, саме це _.isPlainObjectдозволяє мені робити.
вапна

9

Це спрацює. Це функція, яка повертає значення 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


2
@SeregPie Надалі вам слід утримуватися від редагування коду у відповідях. Оскільки ця відповідь стоїть, під час тестування я отримав nullрезультат як для остаточного тесту, а не false. Див. Коли я повинен внести зміни в код?
Нік

9

Оскільки здається велика плутанина щодо того, як правильно впоратися з цією проблемою, я залишу свої 2 копійки (ця відповідь відповідає технічним характеристикам і дає правильні результати за будь-яких обставин):

Тестування на примітиви: undefined null boolean string number

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

Об'єкт не примітив:

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

Або в якості альтернативи:

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

Тестування для будь-якого масиву:

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

Тестування на предмет, що виключає: Date RegExp Boolean Number String Functionбудь-який масив

const isObjectStrict=(function(){
    const nativeTypes=Object.create(null);
    nativeTypes['Date']=true;
    nativeTypes['RegExp']=true;
    nativeTypes['Boolean']=true;
    nativeTypes['Number']=true;
    nativeTypes['String']=true;
    nativeTypes['Function']=true;
    return function(o){
        if (!o) return false;
        return !isPrimitive(o)&&!isArray(o)&&!nativeTypes[o.constructor.name];
    }
}());

8

Коли все інше не вдається, я використовую це:

var isObject = function(item) {
   return item.constructor.name === "Object";
}; 

1
Чому порівняння рядків, чому не просто item.constructor === Object?
K3 --- rnc

nullвикидає винятокUncaught TypeError: Cannot read property 'constructor' of null(…)
Vitim.us

@rounce Я прагну підтримати старіші версії IE, чому це не працює в IE? Через indexOfчи через constructor.name?
Jankapunkt

8

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

Перефразовуючи повну функцію :

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

Мені довелося сміятися, коли зрозумів, наскільки просто і красиво рішення.

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

R.type({}); //=> "Object"
R.type(1); //=> "Number"
R.type(false); //=> "Boolean"
R.type('s'); //=> "String"
R.type(null); //=> "Null"
R.type([]); //=> "Array"
R.type(/[A-z]/); //=> "RegExp"
R.type(() => {}); //=> "Function"
R.type(undefined); //=> "Undefined"

8

Після прочитання і спробувати багато реалізацій, я помітив , що далеко не всі люди намагається перевірити цінності , як JSON, Math, documentабо об'єкти з ланцюжком прототипів більш ніж на 1 крок.

Замість перевірки typeofнашої змінної, а потім злому крайових справ, я подумав, що було б краще, якщо перевірка зберігається якомога простіше, щоб уникнути необхідності рефакторації, коли додаються нові примітиви або натільні об’єкти, які реєструються як typeof"об'єкт" '.

Зрештою, typeofоператор скаже, чи є щось об’єктом JavaScript , але визначення об’єкта JavaScript занадто широке для більшості сценаріїв реального світу (наприклад typeof null === 'object'). Нижче наведена функція, яка визначає, чи vє змінна об'єктом, по суті повторюючи дві перевірки:

  1. Цикл починається , який триває до тих пір , поки строкова версією vє '[object Object]'.
    Я хотів, щоб результат функції був точно таким, як журнали нижче, тому це єдиний "критерій" об'єктивності, з яким я закінчився. Якщо вона не працює, функція повертає помилку відразу.
  2. 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'}))))



6

Якщо явно хочу перевірити, чи задане значення {}.

function isObject (value) {
 return value && typeof value === 'object' && value.constructor === Object;
}

6
const isObject = function(obj) {
  const type = typeof obj;
  return type === 'function' || type === 'object' && !!obj;
};

!!objце стенограма для перевірки того, чи objправда (для фільтрації null)


6

Старе питання, але думав залишити це тут. Більшість людей перевіряє, чи змінна {}означає ключ-значення в парі, а не те, що є підкресленою конструкцією, яку JavaScript використовує для даної речі, тому що чесно кажучи, все, що в JavaScript є об'єктом. Тож виймаючи це з шляху. Якщо ти зробиш...

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

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

Більшу частину часу ми хочемо знати, чи є у нас об’єкт ресурсу з API чи виклик нашої бази даних, що повертається з ORM. Тоді ми можемо перевірити, чи не є Array, ні null, не є typeof 'function'і є 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()
toddmo

1
@toddmo дякую, що вказали на це. Тепер приклад коду повертає помилку дляnew Date()
Гілберт

4

Що я люблю використовувати, це це

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

Я думаю, що в більшості випадків Дата повинна перевірити чек як Об'єкт, тому я не фільтрую дати


4

Я знайшов "новий" спосіб зробити саме такий тип перевірки типу цього питання: Чому 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

Це не може визначити, чи є новий клас об'єктом. isVarTypeOf (new (функція Foo () {}), Object) // Це повертає false замість true. Дивіться мою відповідь нижче для правильної перевірки.
Inanc Gumus

Однак ви можете використовувати instanceofдля перевірки об'єктів. Все-таки це не точна наука.
Inanc Gumus

@inanc, добре, що це тому, що new Foo()повертає Fooоб'єкт, як і new String()повертає Stringоб'єкт, або new Date()повертає Dateоб’єкт, ви можете Foo = function(){}; isVarTypeOf(new Foo(), Foo);також зробити
am05mhz

Так, це те, що я кажу фактично: Ви зараз не перевіряєте, чи це об'єкт.
Інанк Gumus

@inanc Ура, я шукав спосіб зробити перевірку типу (не просто об’єкт), потрапив на цю сторінку та на іншу сторінку, потім я дуже схвильований, що забув контекст цього питання, моє погано :)
am05mhz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.