У JavaScript все є об'єктом (або, принаймні, може трактуватися як об’єкт), за винятком примітивів (булеві значення, null, числа, рядки та значення undefined
(та символ у ES6)):
console.log(typeof true); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof []); // object
console.log(typeof {}); // object
console.log(typeof function () {}); // function
Як ви бачите об'єкти, масиви та значення null
- всі вважаються об'єктами ( null
це посилання на об'єкт, який не існує). Функції розрізняють тим, що вони є особливим типом об'єктів, що дзвоняться . Однак вони все ще є об'єктами.
З іншого боку, літерали true
, 0
, ""
і undefined
не заперечує. Вони є примітивними значеннями в JavaScript. Однак булеві числа, числа та рядки також мають конструктори Boolean
, Number
і String
відповідно, які обертають свої відповідні примітиви, щоб забезпечити додаткову функціональність:
console.log(typeof new Boolean(true)); // object
console.log(typeof new Number(0)); // object
console.log(typeof new String("")); // object
Як ви бачите, коли примітивні значення обернуті всередині Boolean
, Number
а String
конструктори відповідно стають об'єктами. instanceof
Оператор працює тільки для об'єктів (саме тому він повертається false
для примітивних значень):
console.log(true instanceof Boolean); // false
console.log(0 instanceof Number); // false
console.log("" instanceof String); // false
console.log(new Boolean(true) instanceof Boolean); // true
console.log(new Number(0) instanceof Number); // true
console.log(new String("") instanceof String); // true
Як ви бачите і те, typeof
і інше instanceof
недостатньо для перевірки того, чи є значення булевим, числом або рядком - typeof
працює лише для примітивних булів, чисел і рядків; іinstanceof
не працює для примітивних булів, чисел і рядків.
На щастя, існує просте рішення цієї проблеми. Реалізація за замовчуванням toString
(тобто, як це визначено в нашому випадку Object.prototype.toString
) повертає внутрішню [[Class]]
властивість як примітивних значень, так і об'єктів:
function classOf(value) {
return Object.prototype.toString.call(value);
}
console.log(classOf(true)); // [object Boolean]
console.log(classOf(0)); // [object Number]
console.log(classOf("")); // [object String]
console.log(classOf(new Boolean(true))); // [object Boolean]
console.log(classOf(new Number(0))); // [object Number]
console.log(classOf(new String(""))); // [object String]
Внутрішня [[Class]]
властивість значення набагато корисніше typeof
значення. Ми можемо використовувати Object.prototype.toString
для створення власної (більш корисної) версії typeof
оператора наступним чином:
function typeOf(value) {
return Object.prototype.toString.call(value).slice(8, -1);
}
console.log(typeOf(true)); // Boolean
console.log(typeOf(0)); // Number
console.log(typeOf("")); // String
console.log(typeOf(new Boolean(true))); // Boolean
console.log(typeOf(new Number(0))); // Number
console.log(typeOf(new String(""))); // String
Сподіваюся, ця стаття допомогла. Щоб дізнатися більше про відмінності примітивів та загорнутих об'єктів, прочитайте наступну публікацію в блозі: Таємне життя примітивів JavaScript