Оператор typeof
(вместе с instanceof
) — это, вероятно, самая большая недоделка в JavaScript,
поскольку, похоже, он поломан более, чем полностью.
Хотя instanceof
ещё имеет ограниченное применение,
typeof
на самом деле имеет только один практический случай применения,
который при всём при этом не является проверкой типа объекта.
На снимке выше изображён вывод в консоли набора массивов с четырьмя элементами.
Под индексом 0
расположен фрагмент кода, используемый для остальных вычислений.
Под индексом 1
результат интерпретации фрагмента кода браузером (Mozilla Firefox в данном случае).
Под индексом 2
— значение, возвращаемое оператором typeof
— назовём это Тип.
Под индексом 3
— значение внутреннего свойства [[Class]]
объекта — назовём это Класс.
Как хорошо видно, Тип может быть абсолютно любым, но не логичным результатом.
Тип и Класс функций однозначно совпали бы, если бы не Тип function
у регулярных выражений в движках Nitro и V8
(источник — таблица из вдохновляющей статьи).
Для того, чтобы получить значение [[Class]]
, необходимо вызвать метод toString
у Object.prototype
.
Справедливо для ECMAScript 5 и 6
Спецификация предоставляет только один способ доступа к значению [[Class]]
— используя Object.prototype.toString
.
// Получить [[Class]] объекта.
function _getClass(obj) {
return Object.prototype.toString.call(obj).slice(8, -1);
}
// Проверить принадлежность объекта типу.
function _is(type, obj) {
return _getClass(obj) === type;
}
_is('String', 'test'); // true
_is('String', new String('test')); // true
В примере выше Object.prototype.toString
вызывается со значением this
,
являющимся объектом, значение [[Class]]
которого нужно получить.
Из спецификации:
Значением
[[Class]]
может быть одна из следующих строк:Arguments
,Array
,Boolean
,Date
,Error
,Function
,JSON
,Math
,Null
,Number
,Object
,RegExp
,String
,Undefined
.
В реализации браузеров могут также встречаться и другие значения, например:
Crypto
, History
, HTMLCollection
, HTMLDocument
, Location
, Navigator
, Symbol
.
typeof foo !== 'undefined'
Выше проверяется, было ли foo
действительно объявлено или нет;
просто обращение к переменной приведёт к ReferenceError
.
Это единственное, чем на самом деле полезен typeof
.
Для проверки типа объекта настоятельно рекомендуется использовать Object.prototype.toString
— это единственный надёжный способ.
Как показано выше в таблице типов, некоторые возвращаемые typeof
значения не определены в спецификации:
таким образом, они могут отличаться в различных реализациях.
Кроме случая проверки, была ли определена переменная, typeof
следует избегать во что бы то ни стало.
Вдохновение: JavaScript-Garden.