Вопросы на собеседовании по frontend и JavaScript

Что спрашивают у стажёров и джунов во frontend: JavaScript, браузер, CSS и React — плюс три задачи, которые часто дают на live coding.

JavaScript

  1. Чем отличаются var, let и const?

    var видна во всей функции и «всплывает» со значением undefined. let и const живут в блоке и недоступны до объявления (временная мёртвая зона). const запрещает переприсвоение, но объект внутри менять можно.

  2. Что такое замыкание?

    Функция вместе с переменными области, где она создана: она помнит их и после выхода из внешней функции. На этом построены счётчики, фабрики функций, приватные данные, debounce.

  3. Чем == отличается от ===?

    === сравнивает без приведения типов, == сначала приводит ('1' == 1 — true). В коде почти всегда используют ===.

  4. Как определяется this?

    По способу вызова: метод объекта — сам объект; обычный вызов — undefined в строгом режиме; new — новый объект; call/apply/bind — явно заданный. У стрелочных функций своего this нет — берётся из внешней области.

  5. Как работает event loop?

    Синхронный код выполняется в стеке, потом очередь микрозадач (колбэки промисов, queueMicrotask) опустошается целиком, и только затем берётся следующая макрозадача (setTimeout, события). Поэтому Promise.then срабатывает раньше setTimeout(..., 0).

  6. Promise и async/await — в чём разница?

    async/await — синтаксис поверх промисов: код читается последовательно, ошибки ловятся try/catch. Для параллельных запросов — Promise.all (падает на первой ошибке) или Promise.allSettled.

  7. Debounce и throttle — чем отличаются?

    Debounce вызывает функцию после паузы в событиях (поиск по мере ввода). Throttle — не чаще раза в N миллисекунд (скролл, ресайз).

  8. Что такое всплытие событий и делегирование?

    Событие поднимается от элемента к родителям. Делегирование — один обработчик на родителе вместо сотни на детях; нужный элемент находят через event.target.closest(...).

Браузер, CSS и React

  1. Что происходит, когда вводишь адрес в браузере?

    DNS находит IP → TCP- и TLS-соединение → HTTP-запрос → ответ сервера → разбор HTML, построение DOM и CSSOM → layout, paint, композитинг. Скрипты без defer/async блокируют разбор.

  2. Что такое CORS?

    Браузерная защита: скрипт с одного источника может читать ответ другого, только если сервер разрешил это заголовком Access-Control-Allow-Origin. Для «сложных» запросов браузер сначала шлёт предварительный OPTIONS.

  3. Flexbox или Grid?

    Flexbox — раскладка по одной оси: строка кнопок, выравнивание. Grid — двумерная сетка: макет страницы, карточки. Часто используют вместе.

  4. Как считается специфичность CSS?

    Инлайн-стили важнее идентификаторов, идентификаторы — классов, атрибутов и псевдоклассов, те — тегов. При равной специфичности побеждает правило ниже. !important — крайняя мера.

  5. Зачем нужен key в списках React?

    По ключу React сопоставляет элементы между рендерами. Индекс массива как ключ ломает состояние при вставке и удалении — нужен стабильный id.

  6. Как работает useEffect и зачем массив зависимостей?

    Эффект выполняется после рендера; с массивом зависимостей — только когда они изменились, с пустым — один раз после монтирования. Функция, которую эффект возвращает, — очистка: отписки, таймеры.

  7. Почему состояние нельзя мутировать напрямую?

    React сравнивает ссылки: если изменить объект на месте, ссылка та же, и компонент может не перерисоваться. Нужно создавать новый объект или массив (spread, map, filter).

Задачи на live coding

  1. Написать debounce

    Функция возвращает обёртку, которая при каждом вызове сбрасывает таймер (clearTimeout) и ставит новый (setTimeout) с последними аргументами. Не забыть про this и аргументы.

  2. Сгруппировать массив объектов по полю

    reduce в объект: ключ — значение поля, значение — массив. В новых средах есть Object.groupBy, но на собеседовании обычно просят написать самому.

  3. Реализовать Promise.all

    Новый промис, массив результатов и счётчик выполненных. Каждый результат кладём по его индексу; когда счётчик равен длине — resolve, на первой ошибке — reject. Пустой массив — сразу resolve([]).

Как держать задачу под контролем и проговаривать решение — в материале про live coding на собеседовании.