typeof

Оператор typeof ("тип ...") повертає рядок, який вказує на тип значення операнда.

Спробуйте його в дії

Синтаксис

typeof operand

Параметри

operand

Вираз, який позначає об'єкт або примітив, чий тип буде повернено.

Опис

Таблиця нижче наводить всі можливі повернені значення typeof. Більше інформації про типи та примітиви можна знайти на сторінці, присвяченій структурам даних JavaScript.

Тип Результат
Undefined "undefined"
Null "object" (причина)
Boolean "boolean"
Number "number"
BigInt "bigint"
String "string"
Symbol "symbol"
Об'єкт Function (реалізовує [[Call]] у термінах ECMA-262; класи також є функціями) "function"
Будь-який інший об'єкт "object"

Цей список значень є вичерпним. Повідомляють, що рушії, котрі не відповідають специфікації, виробляють (чи історично виробляли) інакші значення, ніж перелічені вище.

Приклади

Елементарне застосування

// Числа
typeof 37 === 'number';
typeof 3.14 === 'number';
typeof 42 === 'number';
typeof Math.LN2 === 'number';
typeof Infinity === 'number';
typeof NaN === 'number'; // Не дивлячись на те, що це "Not-A-Number"
typeof Number('1') === 'number'; // Конструктор Number намагається перетворити значення на числа
typeof Number('shoe') === 'number'; // навіть ті, які неможливо привести до числа

typeof 42n === 'bigint';

// Рядки
typeof '' === 'string';
typeof 'bla' === 'string';
typeof `шаблонний літерал` === 'string';
typeof '1' === 'string'; // зауважте, що число всередині рядка все ж має рядковий тип
typeof (typeof 1) === 'string'; // typeof завжди повертає рядок
typeof String(1) === 'string'; // конструктор String перетворює все на рядок, безпечніше за toString

// Булеві значення
typeof true === 'boolean';
typeof false === 'boolean';
typeof Boolean(1) === 'boolean'; // конструктор Boolean() перетворює значення залежно від того, істинні вони чи хибні
typeof !!1 === 'boolean'; // подвійний виклик оператора ! (логічне НЕ) еквівалентно виклику конструктора Boolean()

// Символи
typeof Symbol() === 'symbol';
typeof Symbol('foo') === 'symbol';
typeof Symbol.iterator === 'symbol';

// Undefined
typeof undefined === 'undefined';
typeof declaredButUndefinedVariable === 'undefined';
typeof undeclaredVariable === 'undefined';

// Об'єкти
typeof { a: 1 } === 'object';

// Для розрізнення звичайних об'єктів від масивів слід
// застосовувати Array.isArray або Object.prototype.toString.call
typeof [1, 2, 4] === 'object';

typeof new Date() === 'object';
typeof /regex/ === 'object'; // історичні результати можна знайти в секції "Регулярні вирази"

// Наступні варіанти — заплутані, небезпечні і марнотратні. Їх слід уникати.
typeof new Boolean(true) === 'object';
typeof new Number(1) === 'object';
typeof new String('abc') === 'object';

// Функції
typeof function () {} === 'function';
typeof class C {} === 'function';
typeof Math.sin === 'function';

typeof null

// Ця рівність зберігається з часів створення JavaScript
typeof null === "object";

В першій реалізації JavaScript, його значення позначалися як тег типу та власне значення. Тег типу для об'єктів був 0. null позначався як нульовим вказівником (на більшості платформ це 0x00). Як наслідок, null мав тег типу 0, тому typeof повертає значення "object". (посилання (англ.))

Було запропоновано виправлення для ECMAScript (як "opt-in" — можливість, яку можна було б увімкнути), проте його відхилили. Результатом його прийняття була б рівність typeof null === 'null'.

Застосування оператора new

Усі функції-конструктори, викликані з new, повернуть непримітиви ("object" чи "function"). Більшість повертає об'єкти, крім вагомого винятку в особі Function, що повертає функцію.

const str = new String("String");
const num = new Number(100);

typeof str; // 'object'
typeof num; // 'object'

const func = new Function();

typeof func; // 'function'

Потреба в дужках в синтаксисі

Оператор typeof має вищий пріоритет, ніж бінарні оператори типу оператора додавання (+). Таким чином, для обчислення типу результату додавання необхідні дужки.

// За допомогою дужок можна визначати тип даних цілих виразів.
const someData = 99;

typeof someData + " Wisen"; // 'number Wisen'
typeof (someData + " Wisen"); // 'string'

Взаємодія з неоголошеними й неініціалізованими змінними

Загалом typeof гарантовано поверне рядок, для будь-якого наданого операнда. Навіть з неоголошеними ідентифікаторами typeof поверне "undefined", а не викине помилку.

typeof undeclaredVariable; // "undefined"

Проте застосування typeof на лексичних оголошеннях (let const і class), в тому ж блоці перед місцем оголошення, викине ReferenceError. Змінні блокової видимості перебувають у темпоральній мертвій зоні від початку блока до обробки ініціалізації, протягом чого така змінна викине помилку, якщо спробувати до неї звернутися.

typeof newLetVariable; // ReferenceError
typeof newConstVariable; // ReferenceError
typeof newClass; // ReferenceError

let newLetVariable;
const newConstVariable = "hello";
class newClass {}

Виняткова поведінка document.all

Всі актуальні браузери дають змогу доступитися до нестандартного об'єкта системного об'єкта document.all з типом undefined.

typeof document.all === "undefined";

Попри те, що document.all також є хибним значенням і приблизно дорівнює undefined, він не є undefined. Ситуація з тим, що document.all має тип "undefined", класифікована у вебстандартах як "навмисне порушення" оригінального стандарту ECMAScript заради сумісності.

Власний метод, що отримує більш конкретний тип

Оператор typeof дуже корисний, проте він не настільки універсальний, наскільки це може бути потрібно. Наприклад, typeof [] дорівнює 'object', так само як typeof new Date(), typeof /abc/ тощо.

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

function type(value) {
  if (value === null) {
    return "null";
  }
  const baseType = typeof value;
  // Примітивні типи
  if (!["object", "function"].includes(baseType)) {
    return baseType;
  }
  // Symbol.toStringTag нерідко вказує на "показне ім'я"
  // класу об'єкта. Він використовується в Object.prototype.toString().
  const tag = value[Symbol.toStringTag];
  if (typeof tag === "string") {
    return tag;
  }
  // Якщо це функція, чий вихідний код починається з ключового слова "class"
  if (
    baseType === "function" &&
    Function.prototype.toString.call(value).startsWith("class")
  ) {
    return "class";
  }
  // Ім'я конструктора; наприклад, `Array`, `GeneratorFunction`,
  // `Number`, `String`, `Boolean` чи `MyCustomClass`
  const className = value.constructor.name;
  if (typeof className === "string" && className !== "") {
    return className;
  }
  // Тут вже немає надійного способа отримати тип значення,
  // тож застосовується базова реалізація.
  return baseType;
}

Для перевірки недійсних змінних, які в іншому випадку викинули б ReferenceError, слід застосовувати typeof nonExistentVar === 'undefined', адже таку поведінку неможливо імітувати за допомогою самописного коду.

Специфікації

Сумісність із браузерами

desktop mobile server
Chrome Edge Firefox Internet Explorer Opera Safari WebView Android Chrome Android Firefox for Android Opera Android Safari on iOS Samsung Internet Deno Node.js
typeof
Chrome Full support 1
Edge Full support 12
Firefox Full support 1
Internet Explorer Full support 3
Opera Full support 3
Safari Full support 1
WebView Android Full support 1
Chrome Android Full support 18
Firefox for Android Full support 4
Opera Android Full support 10.1
Safari on iOS Full support 1
Samsung Internet Full support 1.0
Deno Full support 1.0
Node.js Full support 0.10.0

Дивіться також