JavaScript | Оператор typeof

JavaScript | Оператор typeof

Оглавление

Введение

Где можно найти документацию по работе оператора typeof из JavaScript?

typeof — это зарезервированное слово в JavaScript

Оператор typeof и примитивные значения в JavaScript?

Главная особенность работы оператора typeof в JavaScript

Оператор typeof и функция в JavaScript?

constructor.name вместо typeof

 

Введение

Полезность или бесполезность оператора typeof в JavaScript каждый должен определить для себя сам. В этой публикации я постараюсь со всех возможных сторон взглянуть на работу данного оператора. В сети мне довелось видеть много разнообразных мест его применения и не все из них мне понравились.

Большинство людей путают итог выполнения оператора с результатом получения имени конструктора класса объекта, на который ссылается переменная. Большинство просто хочет знать в каком конструкторе был создан объект.

 

Где можно найти документацию по работе оператора typeof из JavaScript?

Почему JavaScript лучше других языков программирования? Потому что у него есть качественная описательная техническая документация, которая называется ECMAScript. Если говорить точнее, то JavaScript просто использует наработки стандарта ECMAScript. Стандарт живой и постоянно обновляется и поддерживается редакторами.

В стандарте есть раздел «13 ECMAScript Language: Expressions«, который описывает различные «Выражения«. Это такое понятие языка — термин. Нас будет интересовать подраздел «13.5 Unary Operators«, который выделяет «Унарные Операторы«. Их идея заключается в том, что сначала мы пишем название оператора, затем справа ставим как минимум один пробел и затем пишем выражение. То есть унарный оператор работает с «чем-то» одним и это «что-то» находится справа от него.

Оператор typeof описан в разделе «13.5.3 The typeof Operator«. Получается, что оператор typeof является унарным оператором.

Раздел The typeof Operator по стандарту ECMAScript - март 2023
Раздел The typeof Operator по стандарту ECMAScript — март 2023

 

typeof — это зарезервированное слово в JavaScript

В стандарте ECMAScript существует понятие «Зарезервированные Слова» (ReservedWord). Это такие слова, которые нельзя использовать для именования переменных.

Зарезервированное слово typeof среди остальных зарезервированных - ECMAScript
Зарезервированное слово typeof среди остальных зарезервированных — ECMAScript

Вы не сможете объявить переменную с именем «typeof». Это будет синтаксической ошибкой. Среда выполнения кода вам этого не позволит сделать. Программа перестанет работать и всё завалится.

Слово typeof является зарезервированным в JavaScript - им нельзя именовать переменные
Слово typeof является зарезервированным в JavaScript — им нельзя именовать переменные

Результат работы выражений — синтаксическая ошибка «Uncaught SyntaxError: Unexpected token ‘typeof’«.

 

Оператор typeof и примитивные значения в JavaScript?

Стандарт ECMAScript вводит такое понятие как «Примитивные Значения» (primitive value). В разделе «6.1 ECMAScript Language Types» с ними можно ознакомиться подробнее.

На 2023 год их насчитывается семь штук:

  • Undefined
  • Null
  • Boolean
  • Number
  • BigInt
  • Symbol
  • String

Оператор typeof обрабатывает их все и возвращает строку с соответствующим названием типа, кроме null.

Пункты 4 - 10 алгоритма оператора typeof где обрабатываются примитивные значения ECMAScript
Пункты 4 — 10 алгоритма оператора typeof где обрабатываются примитивные значения ECMAScript

Давайте проверим эту логику работы оператора typeof в консоли браузера.

typeof undefined;
typeof null;
typeof '';
typeof Symbol();
typeof true;
typeof 234;
typeof 567n;

Возвращённые результаты в строковом виде:

Результаты работы оператора typeof с примитивными значениями по стандарту ECMAscript
Результаты работы оператора typeof с примитивными значениями по стандарту ECMAscript

Давайте сопоставим результаты со стандартом:

Вызовы typeof с примитивными значения и соответствие стандарту ECMAScript 2023
Вызовы typeof с примитивными значения и соответствие стандарту ECMAScript 2023

Обратите внимание, что у примитива ‘symbol’ нет литерального обозначения на уровне языка. Создание Символа возможно только при помощи конструктора класса Symbol. Именно поэтому там круглые скобки. Все остальные значения были оформлены литерально (хотя это и не обязательно).

Очень интересным можно отметить возвращение строки ‘object‘, при передачи в typeof значения null в качестве единственного операнда. Причём тут ‘object‘? Вообще не понятно. Но важно то, что если мы действительно передадим какой-то объект, то в ответ тоже получим строку ‘object‘.

В итоге становится не понятно что с чем сравнивать. То есть если мы в качестве операнда будем использовать ссылку на объект (на данные), то мы НЕ сможем отличить null от объекта. Пример ниже:

let a = {a:1};
let b = null;
typeof a; // 'object'
typeof b; // 'object'

Скриншот:

Строка со словом object при вызове typeof с null и обычным объектом - ECMAScript
Строка со словом object при вызове typeof с null и обычным объектом — ECMAScript

 

Главная особенность работы оператора typeof в JavaScript

Единственное, чем выделяется typeof на фоне своих собратьев, так это то, что он умеет безопасно заглядывать в список зарегистрированных имён переменных в среде выполнения кода. Именно «Заглядывать».

Второй шаг алгоритма работы оператора typeof в ECMAScript
Второй шаг алгоритма работы оператора typeof в ECMAScript

На втором шаге своего алгоритма проверяется на принадлежность к Ссылочной Записи в среде выполнения кода. В нашем случае мы указываем желаемый идентификатор — ссылку. В этот момент срабатывает ещё одно условие ветвления, которое прогоняет нашу ссылку (идентификатор) через абстрактную операцию IsUnresolvableReference(v).

Абстрактная операция IsUnresolvableReference принимает аргумент V (ссылочная запись) и возвращает логическое значение. При вызове она выполняет следующие действия:

Логика работы абстрактной операции IsUnresolvableReference для Ссылочной Записи по стандарту ECMAScript
Логика работы абстрактной операции IsUnresolvableReference для Ссылочной Записи по стандарту ECMAScript

Что нам это даёт? Через оператор typeof мы можем проверять существование переменной в JavaScript. Но с подвохом.

Представим, что мы объявили только одну переменную, а пытаемся обратиться к двум именам переменных через оператор typeof. Что мы получим?

let x;
typeof x;
typeof y;

Результаты вызовов:

Оператор typeof не может гарантировать наличие или отсутствие идентификатора привязки -имени переменной в среде - JavaScript
Оператор typeof не может гарантировать наличие или отсутствие идентификатора привязки -имени переменной в среде — JavaScript

В обоих случаях мы получаем строку «undefined«. И эта строка не даёт нам 100% ответа о том, есть ли искомый нами идентификатор привязки или нет его. В итоге мы всё равно не можем понять можно ли безопасно обратиться к этому имени переменной или нет. Именно поэтому typeof только «заглядывает«, не «смотрит» внимательно.

Результат, строковое «undefined«, не отвечает нам конкретно:

  • это значение undefined у переменной? (то есть переменная была объявлена, но ей не присвоилось никакого значения)
  • или
  • это отсутствие переменной вовсе? (ни имени, ни значения)

 

Оператор typeof и функция в JavaScript?

Шаг 13 алгоритма работы оператора typeof в ECMAScript
Шаг 13 алгоритма работы оператора typeof в ECMAScript

Алгоритм оператора typeof предполагает отдельное условие для обработки функции в качестве операнда:

typeof function(){};
typeof (()=>{});

Мы делаем вызовы с обычной и стрелочной функциями. У таких функциональных объектов есть внутренний слот [[Call]], поэтому typeof отличает их от всех остальных объектов.

Строка со словом function при вызове typeof со стрелочной и обычной функцией - ECMAScript
Строка со словом function при вызове typeof со стрелочной и обычной функцией — ECMAScript

В результате мы получаем строку «function«.

 

constructor.name вместо typeof

Иногда нам нужно проверять к какому классу принадлежит объект. То есть мы хотим понимать в конструкторе какого класса он был создан.

Для этого нужно использовать объект constructor, который доступен всем реальным объектам JavaScript.

let r = [];
let o = {};
let x = null;
let q = undefined;
let w;

Смотрим на вызовы:

r?.constructor?.name;
o?.constructor?.name;
x?.constructor?.name;
q?.constructor?.name;
w?.constructor?.name;

ВПыва

Безопасное обращение к объекту constructor вместо оператора typeof - JavaScript
Безопасное обращение к объекту constructor вместо оператора typeof — JavaScript

 

Информационные ссылки

Стандарт ECMAScripthttps://tc39.es/ecma262/multipage/