JavaScript собеседование: чеклист из 50 вопросов и задач

Собрали 50 самых частых вопросов и задач, которые встречаются на собеседованиях фронтенд-разработчиков. Каждый вопрос — с кратким ответом и примером кода.

Используйте как чеклист: пройдитесь по списку и проверьте, на каждый вопрос можете ответить уверенно. А если где-то застряли — потренируйтесь решать задачи на Девстанции.


Содержание

  1. Основы языка (1–10)
  2. Типы данных и объекты (11–18)
  3. Функции и замыкания (19–26)
  4. Массивы и методы (27–34)
  5. Асинхронный JavaScript (35–42)
  6. DOM, события, ES6+ (43–50)

Основы языка

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

var — функциональная область видимости, можно переобъявлять.
let — блочная область видимости, нельзя переобъявлять.
const — как let, но нельзя переприсваивать.

var x = 1;
var x = 2; // ok

let y = 1;
let y = 2; // SyntaxError

const z = 1;
z = 2; // TypeError

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

JavaScript перемещает объявления переменных и функций в начало области видимости.
var инициализируется как undefined, let и const остаются в temporal dead zone.

console.log(a); // undefined (var поднята)
var a = 5;

console.log(b); // ReferenceError (let в TDZ)
let b = 10;

3. Что такое strict mode?

Строгий режим JavaScript ("use strict").
Запрещает неявное создание глобальных переменных, дублирование параметров, удаление свойств и другие «опасные» действия.

4. Какие операторы сравнения есть в JavaScript?

== (с приведением типов), === (без приведения), !=, !==. Всегда используйте === — это предсказуемее.

5. Что такое NaN?

NaN — «Not a Number». Результат некорректной математической операции. Уникальное свойство: NaN !== NaN.

typeof NaN; // "number"
isNaN("abc"); // true
Number.isNaN("abc"); // false (лучше использовать этот)

6. Что такое typeof и какие значения он возвращает?

Оператор для определения типа. Возвращает: "string", "number", "boolean", "undefined", "object" (для null тоже!), "function", "symbol", "bigint".

7. Что такое Truthy и Falsy значения?

Falsy: false, 0, "", null, undefined, NaN.
Всё остальное — Truthy (включая [], {}, "0").

8. Как проверить, что переменная — массив?

Array.isArray(variable) — самый надёжный способ. instanceof Array не работает в разных frame.

9. Что такое примитивы и ссылочные типы?

Примитивы (string, number, boolean, null, undefined, symbol, bigint) хранятся по значению. Объекты — по ссылке. Копирование объекта создаёт ссылку, а не копию.

let a = [1, 2, 3];
let b = a;
b.push(4);
console.log(a); // [1, 2, 3, 4] — a тоже изменилась

10. Что такое Template literals?

Шаблонные строки с обратными кавычками. Поддерживают многострочность и интерполяцию через ${}.

const name = "Alice";
const msg = `Hello, ${name}!
How are you?`;

Типы данных и объекты

11. Какие типы данных есть в JavaScript?

8 примитивов: string, number, bigint, boolean, undefined, null, symbol, object. Массивы, функции и даты — это объекты.

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

== приводит типы перед сравнением, === сравнивает и значение, и тип.

0 == ""; // true
0 === ""; // false
null == undefined; // true
null === undefined; // false

13. Как глубоко клонировать объект?

structuredClone(obj) — современный способ. Или рекурсивная функция с JSON.parse(JSON.stringify(obj)) (без Date/RegExp) или ручная рекурсия.

14. Как проверить наличие свойства в объекте?

"key" in obj — проверяет и собственные, и унаследованные.
obj.hasOwnProperty("key") — только собственные.
obj.key !== undefined — простой способ.

15. Что такое деструктуризация?

Извлечение значений из объектов/массивов в переменные.

const { name, age } = { name: "Alice", age: 25 };
const [first, second] = [1, 2, 3];
const { name: alias } = { name: "Alice" }; // alias = "Alice"

16. Что такое spread и rest операторы?

Spread (...) раскрывает массив/объект. Rest собирает оставшиеся элементы в массив.

const arr = [1, 2, 3];
const copy = [...arr]; // spread

function sum(...nums) {
  // rest
  return nums.reduce((a, b) => a + b, 0);
}

17. Как работает Object.keys, Object.values, Object.entries?

Возвращают массив ключей, значений или пар [key, value].

const obj = { a: 1, b: 2 };
Object.keys(obj); // ["a", "b"]
Object.values(obj); // [1, 2]
Object.entries(obj); // [["a", 1], ["b", 2]]

18. Что такое Optional chaining (?.) и Nullish coalescing (??)?

?. безопасно обращается к свойствам (возвращает undefined вместо ошибки).
?? возвращает правый операнд только если левый null или undefined.

const user = { address: { city: "Moscow" } };
user?.address?.zip; // undefined (без ошибки)
null ?? "default"; // "default"
0 ?? "default"; // 0 (не "default", потому что 0 !== null)

Функции и замыкания

19. Чем Function declaration отличается от Function expression?

Declaration поднимается (можно вызвать до объявления). Expression нет.

greet(); // ok (declaration)
function greet() {
  console.log("Hi");
}

sayHi(); // ReferenceError (expression)
const sayHi = function () {
  console.log("Hi");
};

20. Что такое стрелочные функции?

Краткий синтаксис.
Отличия: нет своего arguments, нет своего this (берёт из внешнего контекста), нельзя использовать как конструктор.

const add = (a, b) => a + b;
const square = (x) => x * x; // один аргумент — скобки необязательны

21. Что такое замыкание (closure)?

Функция «запоминает» переменные из внешней области видимости, даже после завершения внешней функции.

function counter() {
  let count = 0;
  return {
    increment: () => ++count,
    getCount: () => count,
  };
}
const c = counter();
c.increment(); // 1
c.increment(); // 2
c.getCount(); // 2

22. Как работает this?

Зависит от того, как вызвана функция:

  • Глобальный контекст: window (или undefined в strict mode)
  • Метод объекта: сам объект
  • Конструктор: новый объект
  • Стрелочная функция: this из внешнего контекста
  • call/apply/bind: явно заданный контекст

23. Что делают call, apply и bind?

call — вызывает функцию с указанным this и аргументами через запятую.
apply — то же, но аргументы массивом.
bind — возвращает новую функцию с фиксированным this.

function greet(greeting) {
  console.log(`${greeting}, ${this.name}`);
}
const user = { name: "Alice" };
greet.call(user, "Hello"); // "Hello, Alice"
greet.apply(user, ["Hello"]); // "Hello, Alice"
const bound = greet.bind(user);
bound("Hi"); // "Hi, Alice"

24. Что такое IIFE?

Immediately Invoked Function Expression — функция, которая вызывается сразу после объявления.

(function () {
  const private = 42;
  console.log(private);
})();

25. Как реализовать debounce?

function debounce(fn, delay) {
  let timerId = null;
  return function (...args) {
    clearTimeout(timerId);
    timerId = setTimeout(() => fn.apply(this, args), delay);
  };
}

26. Как реализовать throttle?

function throttle(fn, limit) {
  let inThrottle = false;
  return function (...args) {
    if (!inThrottle) {
      fn.apply(this, args);
      inThrottle = true;
      setTimeout(() => (inThrottle = false), limit);
    }
  };
}

Массивы и методы

27. Что делают map, filter, reduce?

map — преобразует каждый элемент.
filter — оставляет элементы по условию.
reduce — накапливает результат.

[1, 2, 3].map((x) => x * 2); // [2, 4, 6]
[1, 2, 3].filter((x) => x > 1); // [2, 3]
[1, 2, 3].reduce((sum, x) => sum + x, 0); // 6

28. Что делают find, some, every?

find — первый подходящий элемент.
some — есть ли хотя бы один подходящий.
every — все ли подходят.

[1, 2, 3].find((x) => x > 1); // 2
[1, 2, 3].some((x) => x > 2); // true
[1, 2, 3].every((x) => x > 0); // true

29. Чем splice отличается от slice?

splice изменяет исходный массив (удаляет/добавляет элементы).
slice возвращает новый массив без изменения оригинала.

const arr = [1, 2, 3, 4, 5];
arr.splice(1, 2); // arr = [1, 4, 5], вернул [2, 3]
arr.slice(1, 3); // вернул [4, 5], arr не изменился

30. Как развернуть массив?

const arr = [1, 2, 3];
arr.reverse(); // изменяет оригинал
[...arr].reverse(); // создаёт копию
arr.toReversed(); // ES2023 — не изменяет оригинал

31. Как получить уникальные элементы массива?

const arr = [1, 2, 2, 3, 3, 3];
[...new Set(arr)]; // [1, 2, 3]

32. Как сделать flatten массива?

const arr = [1, [2, [3, 4], 5], 6];
arr.flat(Infinity); // [1, 2, 3, 4, 5, 6]

// Ручная реализация:
function flatten(arr) {
  return arr.reduce(
    (acc, item) => acc.concat(Array.isArray(item) ? flatten(item) : item),
    [],
  );
}

33. Как разбить массив на чанки?

function chunk(arr, size) {
  const result = [];
  for (let i = 0; i < arr.length; i += size) {
    result.push(arr.slice(i, i + size));
  }
  return result;
}
chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]

34. Как отсортировать массив чисел?

const arr = [3, 1, 4, 1, 5, 9];
arr.sort((a, b) => a - b); // [1, 1, 3, 4, 5, 9]
// Без compareFn sort сортирует как строки!

Асинхронный JavaScript

35. Что такое Callback и Callback hell?

Callback — функция, переданная как аргумент другой функции.
Callback hell — вложенные друг в друга колбэки, которые khó читать.

getData(function (a) {
  getMoreData(a, function (b) {
    getEvenMoreData(b, function (c) {
      console.log(c);
    });
  });
});

36. Что такое Promise?

Объект, представляющий результат асинхронной операции.
Три состояния: pending, fulfilled, rejected.

const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve("done"), 1000);
});
promise.then((result) => console.log(result));

37. Что делают then, catch, finally?

then — обрабатывает успешный результат.
catch — обрабатывает ошибку.
finally — выполняется в любом случае.

fetch("/api/data")
  .then((res) => res.json())
  .catch((err) => console.error(err))
  .finally(() => hideSpinner());

38. Что делают Promise.all, Promise.race, Promise.allSettled?

all — ждёт все промисы, реджектится при первой ошибке.
race — первый завершившийся (успех или ошибка).
allSettled — ждёт все, возвращает статус каждого.

Promise.all([p1, p2, p3]); // [r1, r2, r3]
Promise.race([p1, p2, p3]); // r1 (если p1 быстрее)
Promise.allSettled([p1, p2, p3]); // [{status: "fulfilled", ...}, ...]

39. Как работает async/await?

async — функция всегда возвращает промис.
await — приостанавливает выполнение до завершения промиса.

async function getData() {
  try {
    const res = await fetch("/api/data");
    const data = await res.json();
    return data;
  } catch (err) {
    console.error(err);
  }
}

40. Что такое Event loop?

Механизм обработки асинхронных операций в JavaScript. Макрозадачи (setTimeout, fetch) выполняются по очереди. Микрозадачи (Promise, queueMicrotask) — приоритетнее.

console.log("1");
setTimeout(() => console.log("2"), 0);
Promise.resolve().then(() => console.log("3"));
console.log("4");
// Вывод: 1, 4, 3, 2

41. Что такое Promise.all с последовательным выполнением?

async function sequence(promises) {
  const results = [];
  for (const p of promises) {
    results.push(await p);
  }
  return results;
}

42. Как обработать ошибки в async/await?

// Способ 1: try/catch
async function foo() {
  try {
    await riskyOperation();
  } catch (err) {
    handleError(err);
  }
}

// Способ 2: .catch() на промисе
async function bar() {
  await riskyOperation().catch(handleError);
}

DOM, события, ES6+

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

Обработчик вешается на родителя, а определение целевого элемента через event.target. Эффективнее, чем вешать обработчик на каждый дочерний элемент.

document.querySelector("ul").addEventListener("click", (e) => {
  if (e.target.tagName === "LI") {
    console.log(e.target.textContent);
  }
});

44. Чем stopPropagation отличается от preventDefault?

stopPropagation останавливает всплытие/погружение события.
preventDefault отменяет действие браузера по умолчанию (переход по ссылке, отправку формы).

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

Cross-Origin Resource Sharing — механизм безопасности браузера. Блокирует запросы с другого домена, если сервер не добавил заголовок Access-Control-Allow-Origin.

46. Как работает LocalStorage?

Хранит данные в браузере без времени жизни. Данные — строки. Максимум ~5-10 МБ. Доступны между вкладками.

localStorage.setItem("key", JSON.stringify({ a: 1 }));
const data = JSON.parse(localStorage.getItem("key"));

47. Что такое Proxy и Reflect?

Proxy перехватывает операции над объектом (чтение, запись, удаление). Reflect предоставляет стандартные методы для этих перехватов.

const handler = {
  get(target, prop) {
    return prop in target ? target[prop] : "default";
  },
};
const proxy = new Proxy({ name: "Alice" }, handler);
proxy.name; // "Alice"
proxy.age; // "default"

48. Что такое Symbol?

Уникальный и неизменяемый примитив. Часто используется как ключ свойства.

const id = Symbol("id");
const obj = { [id]: 42 };
obj[id]; // 42

49. Что такое итератор и Generator?

Итеративный объект имеет метод next() с {value, done}. Generator — функция с yield, возвращающая итератор.

function* range(start, end) {
  for (let i = start; i <= end; i++) {
    yield i;
  }
}
const gen = range(1, 3);
gen.next(); // { value: 1, done: false }
gen.next(); // { value: 2, done: false }
gen.next(); // { value: 3, done: false }
gen.next(); // { value: undefined, done: true }

50. Как реализовать глубокую копию объекта?

const original = { a: 1, b: { c: 2 } };

const copy1 = { ...original };
const copy2 = Object.assign({}, original);
const copy3 = structuredClone(original); // глубокая копия

// spread и Object.assign - поверхностная копия (вложенные объекты по ссылке)

Как подготовиться дальше

Этот чеклист — основа. Но на собеседовании спрашивают не только теорию — просят написать код, объяснить решение, обсудить архитектуру.

Попробуйте решить задачи на Девстанции — здесь есть десятки задач разной сложности с автоматической проверкой и AI-ревью кода. Это лучший способ закрепить знания на практике.

А если готовитесь к конкретному собеседованию — посмотрите план подготовки за неделю и 10 задач с разбором решений.