В JavaScript все является объектом (или, по крайней мере, может рассматриваться как объект), за исключением примитивов (логические, нулевые, числа, строки и значение 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. Однако Booleans, число и строка также имеют конструктор 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