На каждом собеседовании фронтенд-разработчика sooner или later просят написать код. Не на доске, не в документации, а прямо в редакторе — быстро, чисто и с объяснением.
Собрали 10 задач, которые встречаются чаще всего. Разобрали каждую: как подходить к решению, какие ошибки избегать и как показать себя с лучшей стороны.
А чтобы знания не оставались теорией — попробуйте решить эти задачи на практике на Девстанции. Там же можно потренироваться на десятках других задач с автоматической проверкой и AI-ревью кода.
Задача-классика. Звучит просто: вывести числа от 1 до 100, но вместо числа, кратного 3, вывести «Fizz», вместо кратного 5 — «Buzz», а если число кратно обоим — «FizzBuzz».
Почему спрашивают: проверяют базовое понимание условий, оператора остатка от деления и циклов. Звучит тривиально, но на практике многие ошибаются с порядком проверок.
Решение:
function fizzBuzz(n) {
const result = [];
for (let i = 1; i <= n; i++) {
if (i % 15 === 0) {
result.push("FizzBuzz");
} else if (i % 3 === 0) {
result.push("Fizz");
} else if (i % 5 === 0) {
result.push("Buzz");
} else {
result.push(i);
}
}
return result;
}Совет на собеседовании: сначала спросите про граничные случаи — что делать с 0, отрицательными числами, нечисловым входом. Это покажет, что вы думаете о edge cases, а не просто кодите.
Дана строка. Нужно вернуть её в обратном порядке. Казалось бы — split, reverse, join. Но на собеседовании часто просят решить без встроенных методов или написать наивную реализацию.
Почему спрашивают: задача на понимание строк, индексов и алгоритмов. Часто просят оптимизировать или решить разными способами.
Решение:
function reverseString(str) {
let result = "";
for (let i = str.length - 1; i >= 0; i--) {
result += str[i];
}
return result;
}Альтернатива через рекурсию:
function reverseString(str) {
if (str.length <= 1) return str;
return reverseString(str.slice(1)) + str[0];
}Совет на собеседовании: сначала напишите простое решение, затем предложите оптимизацию. Покажите, что умеете думать итеративно и рекурсивно.
Строка — палиндром, если она читается одинаково в обоих направлениях. Нужно написать функцию, которая это проверяет.
Почему спрашивают: задача на строки, циклы и понимание того, что считать «равным» (учитываем ли регистр, пробелы, знаки препинания).
Решение:
function isPalindrome(str) {
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, "");
const len = cleaned.length;
for (let i = 0; i < len / 2; i++) {
if (cleaned[i] !== cleaned[len - 1 - i]) {
return false;
}
}
return true;
}Совет на собеседовании: уточните условия — «racecar» и «Racecar» это одинаково? А «A man, a plan, a canal: Panama»? Покажите, что вы работаете с требованиями, а не гадаете.
Дан массив из n чисел от 1 до n+1. Одно число пропущено. Нужно его найти.
Почему спрашивают: проверяют знание математики, множеств и умение выбирать оптимальный алгоритм.
Решение через сумму:
function findMissing(arr) {
const n = arr.length + 1;
const expectedSum = (n * (n + 1)) / 2;
const actualSum = arr.reduce((sum, num) => sum + num, 0);
return expectedSum - actualSum;
}Решение через Set:
function findMissing(arr) {
const full = new Set(Array.from({ length: arr.length + 1 }, (_, i) => i + 1));
for (const num of arr) full.delete(num);
return [...full][0];
}Совет на собеседовании: объясните сложность каждого решения. Первое — O(n) по времени и O(1) по памяти. Второе — O(n) по обоим. Это покажет понимание Big O.
Дан вложенный массив: [1, [2, [3, 4], 5], 6]. Нужно превратить его в плоский: [1, 2, 3, 4, 5, 6].
Почему спрашивают: задача на рекурсию и понимание структур данных. Часто просят решить без flat().
Рекурсивное решение:
function flatten(arr) {
const result = [];
for (const item of arr) {
if (Array.isArray(item)) {
result.push(...flatten(item));
} else {
result.push(item);
}
}
return result;
}Решение через стек:
function flatten(arr) {
const stack = [...arr];
const result = [];
while (stack.length) {
const item = stack.pop();
if (Array.isArray(item)) {
stack.push(...item);
} else {
result.unshift(item);
}
}
return result;
}Совет на собеседовании: спросите про глубину вложенности. Если она гарантированно мелкая — рекурсия безопасна. Если нет — итеративное решение надёжнее.
Реализовать функцию debounce, которая откладывает вызов функции до тех пор, пока не пройдёт задержка после последнего вызова.
Почему спрашивают: это реальная задача из фронтенда. Debounce используется для обработки ввода, скролла, ресайза. Проверяют понимание замыканий и таймеров.
Решение:
function debounce(fn, delay) {
let timerId = null;
return function (...args) {
clearTimeout(timerId);
timerId = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}Совет на собеседовании: обсудите применение — поиск с debounce, обработку ресайза, отправку аналитики. Покажите, что знаете, зачем это нужно в реальном проекте.
Написать свою функцию myPromiseAll, которая принимает массив промисов и возвращает один промис, который резолвится массивом результатов.
Почему спрашивают: глубокое понимание промисов, асинхронного JavaScript и обработки ошибок.
Решение:
function myPromiseAll(promises) {
return new Promise((resolve, reject) => {
const results = [];
let completed = 0;
if (promises.length === 0) {
resolve(results);
return;
}
promises.forEach((promise, index) => {
Promise.resolve(promise).then(
(value) => {
results[index] = value;
completed++;
if (completed === promises.length) {
resolve(results);
}
},
(error) => {
reject(error);
},
);
});
});
}Совет на собеседовании: объясните, почему важен индекс — промисы могут завершаться в любом порядке, но результаты должны сохранить исходный порядок. Также обсудите, что делает Promise.resolve — обёртка для не-промисов.
Написать функцию, которая создаёт глубокую копию объекта. Вложенность произвольная, могут быть массивы, даты, null.
Почему спрашивают: проверяют понимание ссылочных типов, рекурсии и edge cases (циклические ссылки, специальные объекты).
Решение:
function deepClone(obj, seen = new WeakMap()) {
if (obj === null || typeof obj !== "object") return obj;
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
if (seen.has(obj)) return seen.get(obj);
const clone = Array.isArray(obj) ? [] : {};
seen.set(obj, clone);
for (const key of Object.keys(obj)) {
clone[key] = deepClone(obj[key], seen);
}
return clone;
}Совет на собеседовании: упомяните structuredClone — в современных браузерах это встроенный способ. Но объясните, почему знание ручной реализации важно — для понимания принципов и для поддержки старых сред.
Дан массив и число size. Разбить массив на подмассивы по size элементов.
Почему спрашивают: простая задача, но показывает умение работать с индексами и понимать паттерны итерации.
Решение:
function chunk(arr, size) {
const result = [];
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size));
}
return result;
}Решение через reduce:
function chunk(arr, size) {
return arr.reduce((result, _, i) => {
if (i % size === 0) {
result.push(arr.slice(i, i + size));
}
return result;
}, []);
}Совет на собеседовании: обсудите edge cases — что если size больше длины массива? Что если size равен 0 или отрицательный? Покажите, что думаете о валидации.
Дана матрица (массив массивов). Нужно транспонировать её — строки становятся столбцами.
Почему спрашивают: задача на двумерные массивы, индексы и понимание структур данных. Часто встречается в задачах на алгоритмы.
Решение:
function transpose(matrix) {
const rows = matrix.length;
const cols = matrix[0].length;
const result = [];
for (let j = 0; j < cols; j++) {
result[j] = [];
for (let i = 0; i < rows; i++) {
result[j][i] = matrix[i][j];
}
}
return result;
}Однострочник (для красоты):
const transpose = (m) => m[0].map((_, i) => m.map((row) => row[i]));Совет на собеседовании: начните с классического решения с циклами — оно понятнее и демонстрирует понимание. Однострочник покажите как альтернативу, но объясните, почему классическое решение лучше для читаемости.
Эти 10 задач — лишь верхушка айсберга. На реальном собеседовании могут спросить что угодно от реализации виртуального скролла до написания собственного хука.
Лучший способ подготовиться — решать задачи регулярно, а не зубрить ответы. Попробуйте задачи на Девстанции — здесь есть десятки задач разной сложности с автоматической проверкой и AI-ревью кода, которое подскажет, как написать лучше.
И помните: на собеседовании важен не только ответ, но и как вы к нему пришли. Объясняйте мысли, задавайте вопросы, обсуждайте альтернативы. Это и есть профессиональный подход.