Как пройти собеседование по JavaScript: топ вопросов и ответов

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Как пройти собеседование по JavaScript: топ вопросов

Собеседование на позицию JavaScript-разработчика (особенно с фокусом на Node.js) — это не просто проверка синтаксиса. Работодатели хотят видеть глубокое понимание асинхронности, областей видимости и работы Event Loop. В этой статье мы собрали топ вопросов, которые действительно задают на собеседованиях, с примерами кода и пояснениями.

1. Замыкания (Closures) — основа функционального JS

Вопрос: "Что такое замыкание и как оно работает в Node.js?"

Замыкание — это функция, которая "запоминает" своё лексическое окружение даже после того, как внешняя функция завершила выполнение. Это ключевой механизм для инкапсуляции данных в JavaScript.

function createCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

Почему это спрашивают: Замыкания лежат в основе модулей, фабрик функций и обработчиков событий в Node.js. Без понимания замыканий невозможно работать с асинхронными колбэками.

2. Event Loop и асинхронность (Async/Await, Promises)

Вопрос: "Объясните, как работает Event Loop. Что выведет этот код?"

console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

Ответ: 1, 4, 3, 2. Сначала синхронный код, затем микрозадачи (Promise.then), затем макрозадачи (setTimeout).

Event Loop — это механизм, который позволяет Node.js выполнять неблокирующие операции, несмотря на однопоточность. Он состоит из нескольких фаз:

  • Таймеры — выполняют колбэки setTimeout/setInterval
  • I/O колбэки — обработка завершённых операций ввода-вывода
  • Poll (опрос) — получение новых I/O событий
  • Check — выполнение setImmediate()
  • Close callbacks — закрытие соединений

Совет: На собеседовании покажите понимание разницы между process.nextTick() и setImmediate(). nextTick выполняется перед следующей фазой Event Loop, а setImmediate — в фазе Check.

3. Контекст вызова (this) и стрелочные функции

Вопрос: "Чему равен this в разных ситуациях? Как изменить контекст?"

Значение this определяется тем, как вызвана функция, а не где она объявлена. В Node.js (строгий режим) в обычной функции this будет undefined, а в браузере — window.

const obj = {
  name: 'Node.js',
  regularFunc: function() {
    console.log(this.name);
  },
  arrowFunc: () => {
    console.log(this.name);
  }
};

obj.regularFunc(); // 'Node.js'
obj.arrowFunc();   // undefined (this берётся из внешнего контекста)

Как управлять контекстом:

  • call(thisArg, arg1, arg2) — вызывает функцию с указанным this и аргументами
  • apply(thisArg, [args]) — аналогично, но аргументы передаются массивом
  • bind(thisArg) — создаёт новую функцию с привязанным this
  • Стрелочные функции — не имеют собственного this, используют лексический контекст

4. Прототипы и наследование (Prototype Chain)

Вопрос: "Как работает прототипное наследование в JavaScript? В чём отличие от классов?"

JavaScript использует прототипное наследование: каждый объект имеет внутреннюю ссылку [[Prototype]] (доступна через __proto__ или Object.getPrototypeOf()).

function Animal(name) {
  this.name = name;
}

Animal.prototype.speak = function() {
  console.log(`${this.name} издаёт звук`);
};

function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

// Устанавливаем прототип
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.bark = function() {
  console.log('Гав!');
};

const rex = new Dog('Рекс', 'Овчарка');
rex.speak(); // "Рекс издаёт звук"
rex.bark();  // "Гав!"

Современный синтаксис (ES6 классы):

class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log(`${this.name} издаёт звук`);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
  bark() {
    console.log('Гав!');
  }
}

Важно: Классы — это "синтаксический сахар" над прототипами. Они не вводят новую модель наследования, а лишь упрощают запись.

5. Обработка ошибок в Node.js

Вопрос: "Как правильно обрабатывать ошибки в асинхронном коде?"

В Node.js существует несколько паттернов:

  • Callback style (err, result) — первый аргумент всегда ошибка
  • Promises — метод .catch()
  • Async/await — try/catch
// Плохо: потеря ошибки
async function riskyOperation() {
  const data = await fetchData(); // если ошибка — упадёт всё приложение
}

// Хорошо: обработка через try/catch
async function safeOperation() {
  try {
    const data = await fetchData();
    return data;
  } catch (error) {
    console.error('Ошибка получения данных:', error.message);
    throw error; // пробрасываем дальше
  }
}

// Для глобального отлова в Node.js
process.on('uncaughtException', (err) => {
  console.error('Необработанная ошибка:', err);
  process.exit(1); // рекомендуется завершить процесс
});

process.on('unhandledRejection', (reason) => {
  console.error('                

Блоги

Рекомендаций по книгам