JavaScript
Для чего модуль
Собрать не «набор фактов про язык», а рабочую инженерную модель JavaScript: как код реально выполняется, где чаще всего рождаются баги, и как это объяснять на собеседовании и в команде.
Результат после прохождения
- Вы объясняете поведение JS-кода через execution model, а не через заученные исключения.
- Вы уверенно разбираете async-сценарии: порядок выполнения, отмену, гонки, деградацию.
- Вы выбираете структуру данных и стиль преобразований с учетом читаемости и стоимости операций.
- Вы умеете довести «плавающий баг» до воспроизводимости и root cause.
Термины и аббревиатуры
| Термин | Коротко |
|---|---|
TDZ | Временная мертвая зона |
Closure | Функция + внешнее окружение |
Microtask | Приоритетная очередь задач |
Event Loop | Модель выполнения задач |
Prototype | Механизм наследования |
Фокус по грейдам
Junior: понимать базовые механики и объяснять их простыми примерами.Middle: применять тему в продуктовых сценариях с учетом рисков и ограничений.Senior: управлять архитектурными trade-offs, метриками и эволюцией решения.
Как работать с модулем
- Каждый урок проходите в связке: теория -> JS Visual Lab для runtime-механик -> код в консоли/песочнице -> разбор реального кейса.
- Для каждой темы фиксируйте два артефакта: краткое объяснение на 40-60 секунд и мини-кейс «где это ломалось/могло сломаться».
- После урока закрывайте минимум 3 вопроса из банка по этой теме.
Программа модуля
Урок 1. База языка
Цель: закрыть фундаментальные вопросы, на которых сыпятся даже сильные кандидаты.
Каркас мышления
Перед разбором любого куска JS задавайте 4 вопроса:
- Какие здесь типы и как они сравниваются?
- В какой области видимости живут переменные?
- Какое значение
thisв точке вызова? - Как будет найдено свойство: own property или по prototype chain?
Типы и сравнения без магии
В JS важно разделять:
- Primitive values (
string,number,bigint,boolean,null,undefined,symbol). - Objects (включая функции, массивы, даты, map/set).
- Reference equality vs value equality.
console.log(0 === false); // false
console.log(0 == false); // true (coercion)
console.log([] === []); // false (разные ссылки)
const a = { x: 1 };
const b = a;
console.log(a === b); // true
Практическое правило:
в продуктовой логике избегайте неявных сравнений (==) кроме явно понятных кейсов.
Hoisting, scope, TDZ
var hoist-ится с undefined, let/const hoist-ятся в TDZ.
function demo() {
console.log(a); // undefined
// console.log(b); // ReferenceError
var a = 1;
let b = 2;
}
Прод-следствие:
баги из-за случайного var часто выглядят как «иногда undefined в неожиданный момент».
this и prototype chain
this определяется местом вызова, а не местом объявления функции (кроме arrow-function).
const user = {
name: 'Ira',
regular() { return this.name; },
arrow: () => this?.name,
};
console.log(user.regular()); // "Ira"
console.log(user.arrow()); // undefined в strict mode окружении модуля
Prototype chain отвечает за lookup свойств, а не за копирование: это важно при полиморфизме и при дебаге «почему свойство есть в объекте, но не в own keys».
Где ломается в проде
- Случайная мутация объекта из shared state.
- Неверный
thisв callback/handler. - Логика на
==, которая проходит тесты и ломается на edge-case данных.
Мини-задача (обязательная)
Подготовьте 5 объяснений по 40-60 секунд:
var/let/const, ==/===, null/undefined, this, prototype chain.
Для каждого объяснения добавьте один реальный баг-кейс (или правдоподобный сценарий).
Что спросит интервьюер:
почему const не делает объект полностью immutable и где это ломает state в UI.
Критерий готовности по уроку: вы можете предсказать поведение 10 коротких фрагментов кода и объяснить каждое поведение через модель языка.
Урок 2. Асинхронность и runtime
Цель: уметь предсказуемо объяснять порядок выполнения и защищаться от async-багов.
Event Loop: минимальная рабочая модель
- Сначала выполняется sync-код.
- Потом дренируются microtasks (
Promise.then,queueMicrotask). - Потом берется следующая macrotask (
setTimeout, I/O callbacks).
console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');
// A, D, C, B
Promise combinators и выбор по задаче
Promise.all- «все или ошибка», быстрый fail.Promise.allSettled- «получить статус каждого».Promise.race- «первый завершившийся».Promise.any- «первый успешный», иначе AggregateError.
Cancellation и stale-response
Одна из самых частых причин «UI показывает старые данные»: старый запрос завершается позже нового и перетирает state.
let currentController;
async function loadUsers(query) {
currentController?.abort();
currentController = new AbortController();
const res = await fetch(`/api/users?q=${encodeURIComponent(query)}`, {
signal: currentController.signal,
});
return res.json();
}
Где ломается в проде
- «Проглоченные» ошибки в async-цепочке.
- Retry без лимита попыток.
- Неправильная обработка
abort, когда отмена считается «настоящей ошибкой».
Мини-задача (обязательная)
Разберите 5 фрагментов с setTimeout, Promise, async/await:
предскажите порядок логов и объясните, почему именно так.
Отдельно реализуйте fetch с timeout + cancel.
Что спросит интервьюер: как вы предотвращаете гонки запросов при быстром переключении фильтров в UI.
Критерий готовности по уроку: вы можете объяснить порядок выполнения кода и показать рабочую защиту от race-condition в UI/сервисе.
Урок 3. Структуры данных и функциональные подходы
Цель: писать предсказуемый и поддерживаемый код для коллекций и трансформаций.
Выбор структуры данных
Array- упорядоченные коллекции, удобно для трансформаций и рендера.Map- быстрый lookup по ключу и сохранение insertion order.Set- уникальность значений без ручной дедупликации.- Plain object - хорошо для сериализации, но не всегда лучший выбор для динамического словаря.
Чистые функции и контролируемые side effects
Чистая функция: при одинаковых входах всегда одинаковый выход и нет побочных эффектов. Это резко упрощает тестирование и рефакторинг.
function aggregateOrders(orders) {
return orders.reduce(
(acc, order) => {
const total = order.items.reduce((s, i) => s + i.price * i.qty, 0);
acc.count += 1;
acc.revenue += total;
return acc;
},
{ count: 0, revenue: 0 }
);
}
Иммутабельность: shallow vs deep
{ ...obj } копирует только первый уровень.
Если внутри вложенный объект/массив, ссылка сохраняется.
Где это ломается:
- Redux-like state обновляется «как будто immutable», но вложенность мутируется.
memo/shouldComponentUpdateне срабатывают корректно.
Readability vs cleverness
reduce полезен, когда реально есть аккумуляция.
Если логика читается хуже, выбирайте map + filter и промежуточные имена.
Мини-задача (обязательная)
Реализуйте преобразование списка заказов в агрегированную статистику без мутации входа. Добавьте тест на edge-cases: пустой список, заказ без items, невалидная цена.
Что спросит интервьюер:
почему иногда reduce хуже читается, чем комбинация map + filter.
Критерий готовности по уроку: вы выбираете структуру данных осознанно и можете объяснить сложность и читаемость выбранного решения.
Урок 4. Прод-кейсы и дебаг
Цель: перейти от «знаю теорию» к «могу разобрать инцидент».
Runbook: stale data после фильтрации
Пошаговый шаблон:
- Зафиксировать сценарий воспроизведения (какие клики, какой интервал, какие фильтры).
- Снять network timeline и убедиться, что ответы приходят в другом порядке.
- Проверить логику обновления state:
есть ли guard по
requestId/AbortController. - Проверить, нет ли двойного запроса из-за эффекта/ре-рендера.
- Добавить временное логирование
requestId -> response -> state update. - Зафиксировать fix и добавить regression test.
Инструменты, которые должны быть «под рукой»
- Breakpoints + conditional breakpoints.
- Network tab и сортировка по start/end time.
- Performance markers (
performance.mark/measure) для ключевых операций. - Structured logs в консоли для сложных async-цепочек.
Что отличает инженерный дебаг от хаотичного
- У вас есть гипотеза перед каждым действием.
- Каждый шаг уменьшает множество возможных причин.
- После фикса есть защита от повтора (тест, guard, мониторинг).
Мини-задача (обязательная)
Соберите runbook для бага: «иногда показываются устаревшие данные после фильтрации». Добавьте: признаки бага, шаги проверки, root cause, fix, проверку фикса.
Что спросит интервьюер: как вы доказываете, что проблема именно в async flow, а не в API.
Критерий готовности по уроку: вы можете довести плавающий баг до воспроизводимости, локализовать источник и доказать корректность исправления.
Практика
1. Scope, значения и предсказание выполнения
Связка: Junior JS q-1..q-5, Two Sum, свободная практика в Песочнице.
Что сделать:
- Решите
Two Sumчерезconst seen = new Map()иlet i. - До запуска выпишите результат 5 сниппетов с
var,let,const, TDZ,==,===,nullиundefined. - Напишите
isFilled(value)для формы и отдельно объясните поведение0,'0',false,null,undefined,''.
Артефакт: короткая таблица case -> expected result -> why -> interview phrase.
Критерий готовности: вы предсказываете выполнение без запуска и можете объяснить, где значение, ссылка или binding ломают ожидание.
2. Functions, objects, this и closure
Связка: Junior JS q-6..q-8, Get By Path.
Что сделать:
- Соберите один объект
userи сравните method call, detached call,bindи arrow callback. - Реализуйте
createCounter()иonce(fn), затем докажите, что состояние не лежит в global scope. - Решите
Get By Pathтак, чтобы путь безопасно останавливался наnull/undefined.
Артефакт: 3 working snippets с подписью call site -> this/closure/prototype behavior -> risk.
Критерий готовности:
вы объясняете this, closure и prototype lookup через конкретный код, а не через определения.
3. Async runtime и stale data
Связка: Junior JS q-9..q-11,
Middle q-17..q-18,
debug-case из урока про stale data после фильтрации.
Что сделать:
- До запуска предскажите порядок 5 сниппетов с sync code,
Promise.then,queueMicrotask,setTimeoutиawait. - Реализуйте
fetchWithTimeoutAndAbort(url, ms)с отдельной обработкой success, timeout, abort и network error. - Оформите runbook для бага
stale data после фильтрации: признаки, гипотеза, воспроизведение, root cause, fix, проверка фикса.
Артефакт: async trace + runbook, где видно, почему причина именно в гонке/устаревшем response, а не в API.
Критерий готовности: вы объясняете event loop и async bug как цепочку событий во времени и называете защиту от stale response.
4. Collections, immutability и browser boundary
Связка: Junior JS q-12..q-20, Merge Sorted Arrays, Move Zeroes, Group By Field.
Что сделать:
- Решите
Merge Sorted ArraysиMove Zeroesбез мутации входных данных. - Реализуйте
groupBy(items, key)и агрегатор заказов с edge-cases: пустой список, неизвестный статус,null-поле, повтор id. - Составьте таблицу
data -> storage -> lifetime -> XSS/CSRF risk -> mitigationдля theme, draft form, access token и refresh token.
Артефакт: набор функций + ручные проверки ссылок prev === next, edge-case таблица и browser storage risk table.
Критерий готовности:
вы выбираете map/filter/reduce/цикл по задаче, доказываете отсутствие мутации и не путаете JS-код с browser security boundary.
Связь с треками и вопросами
- Если вы готовитесь на Junior: закройте Junior JS q-1..q-20 и 3 задачи в песочнице.
- Если вы уже идете в React/Middle: добавьте Middle q-17..q-18 про async/data flow.
- Если нужно подтянуть интервью-формулировку: пройдите Playbook ответов только после того, как код и runbook уже готовы.
- Контрольная карта: Event Loop, Closure,
this, Prototype, TDZ, Async Race, References и Practice Bridges, строкиJS basics,Async runtime,Collections and immutable data,Browser storage and CORS.
Критерий готовности
Ready:
вы даете ответ на 1-2 минуты по любой теме модуля в формате
модель -> пример кода -> where-it-breaks -> как проверить -> как чинить/предотвращать.
Partial: вы решаете задачи, но объяснение держится на определениях без trace, edge-cases или проверки мутации.
Not ready: вы открываете общий банк вопросов и выбираете случайные темы, не связывая их с конкретным кодом и артефактом.
Артефакты после модуля
- Таблица
case -> expected result -> why -> interview phraseдля scope/equality/TDZ. - 3 working snippets по
this, closure и prototype lookup. fetchWithTimeoutAndAbort+ async trace по microtask/macrotask.- Мини-библиотека утилит:
debounce,throttle,groupBy, immutable update helper. - Runbook на
stale data после фильтрациис доказательством root cause. - Browser storage risk table для токенов, draft form и UI settings.