Что вернёт этот код: typeof (function(){})()
Дан блок кода:
console.log(typeof (function () {})())
Что выведет console.log?
Теория по задаче
Разбор синтаксиса
IIFE (Immediately Invoked Function Expression)
(function(){})()
Это немедленно вызываемое функциональное выражение (IIFE). Разберём его структуру:
( // 1. Открывающая скобка для группировки
function(){} // 2. Функциональное выражение - создаёт функцию
) // 3. Закрывающая скобка группировки
() // 4. Оператор вызова функции - немедленно вызывает то, что перед ним
Важные нюансы:
function(){}без оборачивающих скобок было бы объявлением функции, а не выражением- Скобки вокруг
(function(){})превращают объявление в выражение - К любому выражению, которое возвращает функцию, можно применить
()
Альтернативные формы IIFE
// Все эти формы эквивалентны
(function(){})()
(function(){}())
!function(){}()
+function(){}()
Возвращаемое значение функции
Что возвращает функция без return?
function test() {
// Нет оператора return
}
console.log(test()); // undefined
Правило: Любая функция в JavaScript, которая не возвращает значение явно (через return), возвращает undefined.
const result = (function(){})();
console.log(result); // undefined
console.log(result === undefined); // true
Приоритет операторов
Таблица приоритетов (релевантная часть)
| Приоритет | Тип оператора | Ассоциативность | Операторы |
|---|---|---|---|
| 17 | группировка | слева направо | (...) |
| 16 | вызов функции | слева направо | (...) |
| 16 | typeof | справа налево | typeof |
Ключевой момент: У typeof и оператора вызова () одинаковый приоритет (16), но разная ассоциативность:
typeof— справа налево()— слева направо
Как парсер разбирает выражение
typeof (function(){})()
Шаг 1: Парсер видит выражение и начинает разбор с самого высокого приоритета.
Шаг 2: Группирующие скобки (function(){}) имеют приоритет 17 — обрабатываются первыми:
// После обработки группировки
typeof (FunctionObject)()
// где FunctionObject = function(){}
Шаг 3: Далее есть два оператора с приоритетом 16:
typeof(ассоциативность справа налево)()вызова функции (ассоциативность слева направо)
Из-за ассоциативности вызов функции () связывается теснее с тем, что слева от него, чем typeof:
// Фактический порядок выполнения
typeof ( (function(){})() )
// а не
(typeof (function{}))()
Шаг 4: Выполняется вызов функции:
(function(){})() // возвращает undefined
Шаг 5: К результату применяется typeof:
typeof undefined // возвращает "undefined"
Поведение оператора typeof
Возможные возвращаемые значения
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (историческая особенность)
console.log(typeof true); // "boolean"
console.log(typeof 42); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof Symbol()); // "symbol"
console.log(typeof 123n); // "bigint"
console.log(typeof function(){}); // "function"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"
console.log(typeof /regex/); // "object"
Особенности typeof
Это оператор, а не функция, поэтому скобки не обязательны:
typeof x // работает
typeof(x) // тоже работает, но это не вызов функции
Всегда возвращает строку:
console.log(typeof typeof 42); // "string" (потому что typeof 42 → "number", typeof "number" → "string")
Безопасен с необъявленными переменными:
console.log(typeof undeclaredVar); // "undefined" (не вызывает ReferenceError)
Итого
Ключевые выводы:
(function(){})()— это IIFE, возвращающаяundefined(если нетreturn)- Приоритет операторов заставляет сначала выполнить вызов функции, затем
typeof typeof undefinedвсегда возвращает строку"undefined"- Оператор
typeofбезопасен и всегда возвращает строку с именем типа
Правильный мысленный алгоритм:
- Определи, что это IIFE
- Пойми, что пустая функция возвращает
undefined - Запомни, что
()вызова имеет приоритет надtypeofв этом контексте - Примени
typeofкundefined→ получи"undefined"
Эта задача прекрасно иллюстрирует важность понимания приоритетов операторов в JavaScript и поведения функций по умолчанию.