Как пройти собеседование по JavaScript: топ вопросов
Собеседование на позицию JavaScript-разработчика — это не только проверка синтаксиса, но и глубокое понимание того, как работает язык. Особенно это касается Node.js, где асинхронность и обработка ошибок выходят на первый план. В этой статье мы разобрали топ-10 вопросов, которые чаще всего задают на собеседованиях для Junior и Middle разработчиков. Каждый вопрос сопровождается примером кода и пояснением.
1. Что такое замыкание (closure) и где оно применяется?
Замыкание — это функция, которая «запоминает» свою лексическую область видимости даже после того, как внешняя функция завершила выполнение. Это одна из ключевых концепций JavaScript.
Пример:
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
Где применяется? В модулях, фабриках функций, мемоизации, обработчиках событий и при работе с замыканиями в циклах (например, в setTimeout).
2. Как работает Event Loop в Node.js?
Event Loop — это механизм, который позволяет Node.js выполнять неблокирующие операции, несмотря на однопоточность. Он состоит из нескольких фаз: timers, poll, check и close callbacks.
Пример с микрозадачами:
console.log('1');
setTimeout(() => console.log('2'), 0);
Promise.resolve().then(() => console.log('3'));
console.log('4');
// Вывод: 1, 4, 3, 2
Почему так? Микрозадачи (Promise) выполняются сразу после текущего стека и перед следующей фазой Event Loop.
3. Разница между == и ===
Оператор == сравнивает значения с приведением типов, а === — без приведения (строгое равенство).
console.log(5 == '5'); // true (приведение строки к числу)
console.log(5 === '5'); // false (разные типы)
console.log(null == undefined); // true
console.log(null === undefined); // false
На собеседованиях часто просят объяснить, почему [] == false даёт true (из-за абстрактного сравнения с примитивом).
4. Что такое прототипное наследование?
В JavaScript объекты могут наследовать свойства от других объектов через прототипную цепочку. Каждый объект имеет внутреннее свойство [[Prototype]], доступ к которому можно получить через __proto__ или Object.getPrototypeOf().
Пример:
const animal = { eats: true };
const rabbit = { jumps: true };
rabbit.__proto__ = animal;
console.log(rabbit.eats); // true (наследуется)
console.log(rabbit.jumps); // true
Современный способ — использовать Object.create() или классы (синтаксический сахар над прототипами).
5. Как работает this в JavaScript?
Значение this определяется контекстом вызова функции. Основные правила:
- В глобальном контексте (в браузере) —
window, в Node.js —global. - В методе объекта — сам объект.
- В стрелочной функции — лексический
this(из внешней функции). - При вызове через
call/apply/bind— явно переданный контекст.
Пример:
const obj = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
obj.greet(); // Alice
const greet = obj.greet;
greet(); // undefined (потеря контекста)
const boundGreet = obj.greet.bind({ name: 'Bob' });
boundGreet(); // Bob
6. Промисы: цепочки и обработка ошибок
Промисы — это способ работы с асинхронным кодом. Важно понимать, как строить цепочки и обрабатывать ошибки.
function fetchData(id) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (id > 0) resolve({ id, data: 'OK' });
else reject(new Error('Invalid ID'));
}, 1000);
});
}
fetchData(1)
.then(data => {
console.log(data); // { id: 1, data: 'OK' }
return fetchData(2);
})
.then(data => console.log(data))
.catch(err => console.error(err.message));
Важно: всегда завершайте цепочку .catch(), иначе ошибка может «проглотиться».
7. Что такое hoisting (поднятие)?
Hoisting — это механизм, при котором объявления переменных и функций «поднимаются» в начало своей области видимости до выполнения кода.
console.log(a); // undefined (var поднимается, но не инициализируется)
var a = 5;
// let и const тоже поднимаются, но находятся в "временной мёртвой зоне"
// console.log(b); // ReferenceError
let b = 10;
Функции, объявленные через function, поднимаются целиком, поэтому их можно вызывать до объявления.
8. Как избежать callback hell?
Callback hell — это вложенные колбэки, которые делают код нечитаемым. Решения:
- Использовать Promise и цепочки
.then(). - Использовать async/await.
- Разбивать код на отдельные функции.
Пример с async/await:
async function process() {
try {
const data1 = await fetchData(1);
const data2 = await fetchData(2);
console.log(data1, data2);
} catch (err) {
console.error(err);
}
}