Как подготовиться к собеседованию по JavaScript: полный гайд
Собеседование по JavaScript — это не экзамен в школе, где нужно просто заучить ответы. Это разговор, в котором проверяют не только ваши знания синтаксиса, но и умение мыслить, разбираться в механизмах языка и решать реальные задачи. Если вы чувствуете, что «плаваете» в замыканиях, путаете this и боитесь event loop — не переживайте. Мы подготовили структурированное руководство, которое поможет вам уверенно пройти интервью по JavaScript.
Почему так сложно подготовиться к собеседованию по JS?
JavaScript — язык с душой (и иногда с сюрпризами). Одна и та же функция может вести себя по-разному в зависимости от контекста. Поэтому на собеседовании по JavaScript вас не просто спрашивают «что выведет код» — вас просят объяснить почему. И вот тут-то многие и проваливаются. Но мы научим вас ловить эти подводные камни.
1. Основы, которые нужно знать наизусть
Типы данных и приведение типов
Начнём с базы. В JavaScript есть 7 примитивных типов: string, number, boolean, null, undefined, symbol, bigint — и один сложный: object. Но хитрость в том, что typeof null возвращает "object" — это историческая ошибка, которую нужно знать.
На собеседовании по JavaScript любят спрашивать про неявное приведение типов. Например:
console.log([] + []); // ""
console.log([] + {}); // "[object Object]"
console.log({} + []); // 0 (в консоли браузера)
Почему так? Потому что оператор + пытается привести операнды к примитивам, вызывая toString() или valueOf(). Запомните: пустой массив превращается в пустую строку, а объект — в строку "[object Object]".
Замыкания и лексическое окружение
Это одна из самых частых тем на собеседовании по JavaScript. Замыкание — это функция, которая «запоминает» переменные из своей внешней области видимости даже после того, как внешняя функция завершила работу.
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
На собеседовании вас могут попросить написать подобную функцию или объяснить, почему в цикле с var возникает классическая проблема:
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}
// Выведет 5, 5, 5, 5, 5
Решение — использовать let или обернуть в замыкание. Обязательно объясните, что var имеет функциональную, а не блочную область видимости.
2. «This» — боль и радость каждого JS-разработчика
Вопросы про this — классика жанра. Правило простое: значение this определяется тем, как вызвана функция, а не где она объявлена.
- В глобальном контексте (в браузере)
this— этоwindow. - В методе объекта — сам объект.
- В функции-конструкторе — новый экземпляр.
- В стрелочной функции —
thisиз внешнего лексического окружения.
Пример для собеседования:
const obj = {
name: "JS",
getName: function() {
return this.name;
}
};
const fn = obj.getName;
console.log(fn()); // undefined (контекст потерян)
Как исправить? Использовать bind, call, apply или стрелочную функцию.
3. Event Loop и асинхронность — тема для звёзд
Без понимания event loop вы не пройдёте собеседование по JavaScript среднего уровня. Запомните последовательность: сначала выполняется весь синхронный код (стек вызовов), затем — микротаски (Promise, MutationObserver), потом — макротаски (setTimeout, setInterval).
Вопрос-ловушка:
console.log(1);
setTimeout(() => console.log(2), 0);
Promise.resolve().then(() => console.log(3));
console.log(4);
// Вывод: 1, 4, 3, 2
Объяснение: Promise — микротаска, она выполняется до макротаски setTimeout, даже если задержка 0 мс.
4. Прототипы и наследование
JavaScript — прототипно-ориентированный язык. Каждый объект имеет скрытое свойство [[Prototype]], которое можно получить через Object.getPrototypeOf() или устаревшее __proto__.
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
return `${this.name} издаёт звук`;
};
const dog = new Animal("Бобик");
console.log(dog.speak()); // Бобик издаёт звук
На собеседовании вас могут спросить про цепочку прототипов: как работает поиск свойства — сначала в самом объекте, потом в прототипе, потом в прототипе прототипа и так до null.
5. Реальные задачи на собеседовании по JavaScript
Полифил для bind
Это одна из самых популярных задач. Вас просят написать свою версию bind:
Function.prototype.myBind = function(context, ...args) {
const fn = this;
return function(...innerArgs) {
return fn.apply(context, [...args, ...innerArgs]);
};
};
function greet(greeting) {
return `${greeting}, ${this.name}`;
}
const user = { name: "Анна" };
const boundGreet = greet.myBind(user, "Привет");
console.log(boundGreet()); // Привет, Анна
Плоский массив (flatten)
Напишите функцию, которая превращает вложенный массив в плоский:
function flatten(arr) {
return arr.reduce((acc, val) =>
Array.isArray(val) ? acc.concat(flatten(val)) : acc.concat(val), []);
}
console.log(flatten([1, [2, [3, [4]]]])); // [1, 2, 3, 4]
Debounce и Throttle
Очень частые вопросы. Debounce — откладывает вызов до паузы, throttle — ограничивает частоту вызова.
function debounce(fn, delay) {
let timer;
return function(...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
function throttle(fn, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {