«Что выведет?» — разбор каверзных задач
Три задачи-ловушки, которые встречаются почти на каждом собеседовании.
Эти примеры проверяют понимание трёх тем сразу: поднятия, замыканий и событийного цикла. Разберём каждый по шагам.
Задача 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(макрозадачи).