«Что выведет?» — разбор каверзных задач

Три задачи-ловушки, которые встречаются почти на каждом собеседовании.

Эти примеры проверяют понимание трёх тем сразу: поднятия, замыканий и событийного цикла. Разберём каждый по шагам.

Задача 1: hoisting

Кажется, что переменная не определена. Но var поднимается без значения.

var x = 1;

function test() {
  console.log(x); // какая x?
  var x = 2;
  console.log(x);
}

test();

Вывод:

undefined
2

Внутри функции var x поднимается в начало test и «затеняет» внешнюю x. До присваивания локальная x равна undefined — поэтому первый console.log печатает undefined, а не 1.

Задача 2: замыкание в цикле

const fns = [];
for (var i = 0; i < 3; i++) {
  fns.push(() => i);
}
console.log(fns[0](), fns[1](), fns[2]());

Вывод:

3 3 3

Все три функции замкнулись на одну общую переменную var i. К моменту вызова цикл уже закончился, и i равно 3. Замена var на let дала бы 0 1 2.

Задача 3: порядок промисов

console.log("старт");

setTimeout(() => console.log("таймаут"), 0);

Promise.resolve()
  .then(() => console.log("промис 1"))
  .then(() => console.log("промис 2"));

console.log("конец");

Вывод:

старт
конец
промис 1
промис 2
таймаут

Сначала синхронный код («старт», «конец»). Затем вся очередь микрозадач — цепочка промисов («промис 1», «промис 2»). И только потом макрозадача setTimeout («таймаут»).

Задача 4: typeof и приведение

console.log(typeof typeof 1);
console.log(1 + "1" - 1);
console.log([] + []);
console.log(+"");

Вывод:

string
10
 
0

typeof 1 это строка "number", а typeof "number" — снова "string". 1 + "1" даёт строку "11", затем "11" - 1 приводит к числу и даёт 10. [] + [] — две пустые строки, то есть пустая строка. +"" приводит пустую строку к числу 0.

Итог

  • Локальная var поднимается и затеняет внешнюю — отсюда undefined.
  • Замыкания в цикле с var делят одну переменную — все печатают финальное значение.
  • Промисы (микрозадачи) всегда раньше setTimeout (макрозадачи).
Проверьте себя
1. Что выведет первый console.log(x) внутри функции, где ниже объявлена var x = 2 (а снаружи var x = 1)?
A1
B2
Cundefined
DReferenceError
2. Что выведет 1 + "1" - 1?
A1
B10
C11
DNaN
3. В каком порядке печатаются цепочка .then и setTimeout(0)?
AСначала setTimeout, потом промисы
BСначала все промисы (микрозадачи), потом setTimeout (макрозадача)
CОдновременно
DСлучайно
Поддержать проект