Frontend | Вопросы собесов
18.6K subscribers
36 photos
2 videos
1.33K links
Сайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.me/+T0COHtFzCJkwMDUy
Задачи t.me/+_tcX2w2EmvdmMTgy
Вакансии t.me/+CgCAzIyGHHg0Nzky
Download Telegram
🤔 Как мониторить ошибки JS?

- Через консоль браузера (DevTools);
- Используя системы логирования: Sentry, LogRocket, Bugsnag;
- Локальный лог с console.error и передачей на сервер;
- Performance API, window.onerror, unhandledrejection.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍5🔥5
🤔 Является ли, drag and drop частью спецификации?

Да! Drag and Drop (перетаскивание) — это часть спецификации HTML5. В браузерах есть встроенный API, который позволяет делать перетаскивание элементов без дополнительных библиотек.

🚩Как работает Drag and Drop API?

В HTML5 можно сделать элемент перетаскиваемым, добавив ему атрибут draggable="true". Затем срабатывают специальные события, такие как dragstart, drop, dragover и другие.
<div id="drag-item" draggable="true">Перетащи меня</div>
<div id="drop-zone">Сюда можно сбросить</div>

<script>
const dragItem = document.getElementById("drag-item");
const dropZone = document.getElementById("drop-zone");

dragItem.addEventListener("dragstart", (event) => {
event.dataTransfer.setData("text/plain", "Данные элемента");
});

dropZone.addEventListener("dragover", (event) => {
event.preventDefault(); // Нужно, чтобы разрешить сброс
});

dropZone.addEventListener("drop", (event) => {
event.preventDefault();
const data = event.dataTransfer.getData("text/plain");
alert("Элемент сброшен: " + data);
});
</script>


🚩Какие события есть в Drag and Drop?

Основные события:
dragstart — когда начали тянуть элемент.
drag — когда элемент двигается (срабатывает много раз).
dragenter — когда курсор заходит в зону сброса.
dragover — когда элемент находится над зоной (нужно preventDefault()).
dragleave — когда курсор покидает зону сброса.
drop — когда элемент отпущен в зоне сброса.
dragend — когда перетаскивание завершено (даже если не сбросили).

🚩Где используется Drag and Drop?

- Перетаскивание файлов в <input type="file"> (например, загрузка изображений).
- Канбан-доски, как в Trello.
- Онлайн-редакторы, как Figma.
- Игры, где можно перемещать предметы.

🚩Можно ли сделать Drag and Drop без HTML5 API?


Да, можно использовать другие методы:
Через события мыши (mousedown, mousemove, mouseup).
Через CSS position: absolute и transform.
Через JS-библиотеки (Sortable.js, React DnD, Draggable.js).
Например, в мобильных браузерах стандартный Drag and Drop API плохо работает, и там лучше использовать события touchstart, touchmove, touchend.

Ставь 👍 и забирай 📚 Базу знаний
👍14🔥1
🤔 Примеры того, что можно использовать в useEffect помимо запросов на сервер:

- Слежение за размерами окна (event listener);
- Установка таймера или интервала;
- Работа с локальным хранилищем (localStorage);
- Изменение мета-тегов или заголовков документа;
- Анимации, интеграции с библиотеками (например, chart.js).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍9🔥3🤔1
🤔 Можем ли мы получить картинку по HTTP?

Да, браузер может получить картинку по HTTP, если сервер отдаёт правильный Content-Type (например, image/jpeg).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍14🔥4
🤔 Как определить что состояние является глобальным?

Глобальное состояние – это данные, которые должны быть доступны в разных частях приложения. Чтобы определить, является ли состояние глобальным, нужно задать себе несколько вопросов:

🚩Используется ли это состояние в нескольких независимых компонентах?

Если одно и то же состояние необходимо сразу нескольким компонентам, расположенным в разных частях дерева компонентов, скорее всего, его стоит сделать глобальным. В React, если в разных компонентах нужна информация о текущем пользователе (user), лучше хранить её в глобальном состоянии (например, в Context или Redux).
// Глобальное состояние (например, Context API)
const UserContext = createContext();

function App() {
const [user, setUser] = useState({ name: "Иван", isLoggedIn: true });

return (
<UserContext.Provider value={user}>
<Navbar />
<Profile />
</UserContext.Provider>
);
}

function Navbar() {
const user = useContext(UserContext);
return <div>Привет, {user.name}!</div>;
}

function Profile() {
const user = useContext(UserContext);
return <div>Профиль пользователя: {user.name}</div>;
}


🚩Должно ли состояние сохраняться при переходе между страницами?

Если данные должны оставаться неизменными при смене страниц, лучше использовать глобальное хранилище (например, Redux, Zustand или React Context). Корзина товаров в интернет-магазине
Авторизация пользователя
Темная/светлая тема приложения
Если данные теряются при смене страницы – это сигнал, что их нужно вынести в глобальное хранилище.

🚩Может ли состояние изменяться в одном месте, а использоваться в другом?

Если одно состояние обновляется в одном компоненте, но влияет на работу нескольких других компонентов, оно должно быть глобальным. В чате, если новое сообщение приходит в одном компоненте (ChatInput), а отображается в другом (ChatList), логично хранить все сообщения в глобальном состоянии.
const ChatContext = createContext();

function ChatProvider({ children }) {
const [messages, setMessages] = useState([]);

const sendMessage = (text) => {
setMessages([...messages, { text, id: Date.now() }]);
};

return (
<ChatContext.Provider value={{ messages, sendMessage }}>
{children}
</ChatContext.Provider>
);
}

function ChatList() {
const { messages } = useContext(ChatContext);
return messages.map((msg) => <p key={msg.id}>{msg.text}</p>);
}

function ChatInput() {
const { sendMessage } = useContext(ChatContext);
const [text, setText] = useState("");

return (
<input
value={text}
onChange={(e) => setText(e.target.value)}
onKeyPress={(e) => {
if (e.key === "Enter") {
sendMessage(text);
setText("");
}
}}
/>
);
}


🚩Зависит ли состояние от URL (адресной строки)?

Иногда состояние можно не делать глобальным, а просто хранить его в URL (в query-параметрах или path).
ID открытого товара: /products/123
Фильтры товаров: /shop?category=shoes&sort=price
Страница чата с пользователем: /chat?user=ivan

Ставь 👍 и забирай 📚 Базу знаний
👍6🔥1
🤔 Как передать данные из родительского компонента в дочерний?

Данные передаются с использованием props.
1. Родительский компонент передаёт данные через атрибуты в дочерний компонент.
2. Дочерний компонент принимает их, определяя props в своей конфигурации.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍6🔥6
🤔 Почему map используют чаще, чем объект?

Хотя объекты {} исторически использовались как ассоциативные массивы (ключ-значение), у Map есть ряд преимуществ, которые делают его более удобным в большинстве случаев.

🟠`Map` может использовать любые типы данных в качестве ключей
В объектах {} ключи всегда автоматически приводятся к строке.
const obj = {};
const key1 = {};
const key2 = {};

obj[key1] = "value1";
obj[key2] = "value2";

console.log(obj); // { '[object Object]': 'value2' }
console.log(obj[key1]); // "value2" (ключи перезаписались, потому что оба стали "[object Object]")


Пример с Map:
const map = new Map();
map.set(key1, "value1");
map.set(key2, "value2");

console.log(map.get(key1)); // "value1"
console.log(map.get(key2)); // "value2"


🟠`Map` хранит порядок ключей
В объекте {} порядок ключей не гарантируется (особенно для числовых ключей).
const obj = { 2: "two", 1: "one", 3: "three" };
console.log(Object.keys(obj)); // ["1", "2", "3"] (порядок числовых ключей изменился!)


Пример с Map
const map = new Map();
map.set(2, "two");
map.set(1, "one");
map.set(3, "three");

console.log([...map.keys()]); // [2, 1, 3] (порядок сохраняется!)


🟠`Map` быстрее при частых добавлениях/удалениях
Объекты {} оптимизированы для хранения структуры данных, но операции delete и Object.keys(obj).length могут быть медленными, потому что движок JavaScript выполняет дополнительные проверки.
Разница в скорости
В Map операции .set(), .get(), .delete() выполняются быстрее.
В объекте {} delete obj[key] может работать медленнее, так как JavaScript оптимизирует объекты для других целей.

🟠У `Map` есть удобные методы
Объект {} не имеет встроенных методов для работы с ключами и значениями. Чтобы, например, узнать размер объекта, приходится использовать Object.keys(obj).length.
const map = new Map();
map.set("a", 1);
map.set("b", 2);

console.log(map.size); // 2
console.log(map.has("a")); // true
console.log(map.delete("b")); // true (удалит "b")


В объекте {}
const obj = { a: 1, b: 2 };

console.log(Object.keys(obj).length); // 2 (нужно вызывать Object.keys())
console.log(obj.hasOwnProperty("a")); // true (менее удобный синтаксис)
delete obj.b; // Удаление ключа


🟠`Map` не имеет проблем с прототипами
В объекте {} могут быть неожиданные проблемы, если ключ совпадает с именем встроенного метода.
const obj = {};
console.log(obj.toString); // [Function: toString] (унаследованное свойство!)
console.log(obj["toString"]); // [Function: toString] (может вызвать баги)


Чтобы обойти это, приходится делать так
const obj = Object.create(null); // Теперь у объекта нет прототипа
obj.toString = "custom";
console.log(obj.toString); // "custom"


В Map таких проблем нет
const map = new Map();
map.set("toString", "custom");
console.log(map.get("toString")); // "custom" (никаких багов!)


Ставь 👍 и забирай 📚 Базу знаний
👍17
🤔 Как работает поток данных между Redux и компонентом?

Компонент получает данные из Redux через функции useSelector или connect(). При изменении состояния Redux происходит перерисовка. Чтобы изменить состояние, компонент диспатчит action через dispatch.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
1👍6🔥2
🤔 Что такое merge и rebase, в чем отличие друг от друга?

Это два способа интеграции изменений из одной ветки в другую в системе контроля версий Git. Оба метода имеют свои особенности и подходят для разных сценариев.

🚩Merge (слияние)

Объединяет изменения из одной ветки в другую, создавая новый коммит слияния (merge commit). Этот метод сохраняет историю всех коммитов, включая все ветвления и слияния.
Предположим, у вас есть две ветки: main и feature.
В ветке feature вы сделали несколько коммитов.
Вы хотите объединить изменения из feature в main.
git checkout main
git merge feature


🚩Rebase (перебазирование)

Перемещает или переписывает базу текущей ветки на указанную базу другой ветки. Это переписывает историю коммитов, создавая новые коммиты для каждого из оригинальных коммитов.
Предположим, у вас есть две ветки: main и feature.
В ветке feature вы сделали несколько коммитов.
Вы хотите перенести изменения из feature на текущий конец main.
git checkout feature
git rebase main


🚩Основные отличия

🟠История коммитов
Merge: Сохраняет всю историю, включая коммиты слияния. История показывает, когда и как происходили слияния веток.
Rebase: Переписывает историю, делая её линейной. История показывает, как если бы все изменения были сделаны последовательно, без ветвлений.

🟠Коммиты слияния
Merge: Создает новый коммит слияния, который объединяет изменения из двух веток.
Rebase: Не создает коммит слияния. Перебазирование "переносит" коммиты одной ветки на другую.

🟠Конфликты
Merge: Конфликты решаются один раз при слиянии.
Rebase: Конфликты могут возникнуть на каждом коммите, и их нужно решать поэтапно.

🟠Применение
Merge: Хорош для сохранения полного контекста истории разработки, особенно в командной работе.
Rebase: Хорош для поддержания чистой, линейной истории, особенно перед слиянием ветки в основную ветку, например, main или master.

Ставь 👍 и забирай 📚 Базу знаний
👍7
🤔 Какие способы сортировки массива есть?

В JavaScript массивы сортируются с помощью метода sort()
Также можно использовать:
- Сортировку по строкам (по умолчанию): arr.sort()
- Сортировку по свойствам объектов:
- users.sort((a, b) => a.age - b.age);
- Создание новых отсортированных массивов без мутации:
- const sorted = [...arr].sort();


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍7🔥2
🤔 Как считается вес селектора?

Вес селектора (специфичность) – это правило, по которому браузер определяет, какой стиль применить, если есть несколько конфликтующих селекторов.
( inline, id, class/атрибут/псевдокласс, элемент/псевдоэлемент )


Пример
/* Специфичность: (0, 1, 0, 0) */
#header { color: red; }

/* Специфичность: (0, 0, 1, 0) */
.header { color: blue; }

/* Специфичность: (0, 0, 0, 1) */
h1 { color: green; }


🟠Примеры сравнения специфичности
Пример 1
h1 { color: red; } /* (0,0,0,1) */
.title { color: blue; } /* (0,0,1,0) */


Пример 2
h1 { color: red; } /* (0,0,0,1) */
#main { color: blue; } /* (0,1,0,0) */


Пример 3 (комбинированные селекторы)
h1.title { color: red; } /* (0,0,1,1) */
#main h1 { color: blue; } /* (0,1,0,1) */


Пример 4 (инлайн-стиль всегда сильнее)
<h1 style="color: green;">Заголовок</h1>

h1 { color: red; } /* (0,0,0,1) */
.title { color: blue; } /* (0,0,1,0) */
#main { color: purple; } /* (0,1,0,0) */


🟠Как повысить вес селектора?
Добавить ID (но не злоупотреблять). Использовать более специфичные селекторы (например, .header h1 вместо h1). Использовать !important (но осторожно!).
h1 { color: red !important; } /* Всегда будет красным */


Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Что такое псевдоэлемент?

Псевдоэлемент — это CSS-конструкция, которая позволяет стилизовать определённые части элемента, например, ::before для добавления контента перед элементом или ::after для добавления после. Это удобно для оформления, не изменяя HTML-структуру.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍6
🤔 Что такое шаблонные литералы, и для чего они нужны?

Были введены в ECMAScript 2015 (ES6) и представляют собой улучшение стандартных строк в JavaScript. Они облегчают работу с строками, предоставляя более удобный синтаксис для создания многострочных строк, интерполяции переменных и встроенных выражений.

🚩Примеры использования

🟠Интерполяция переменных и выражений
Шаблонные литералы позволяют встраивать переменные и выражения внутрь строк с помощью синтаксиса ${}.
const name = 'Alice';
const age = 25;

const greeting = `Hello, my name is ${name} and I am ${age} years old.`;

console.log(greeting);
// Вывод: Hello, my name is Alice and I am 25 years old.


🟠Многострочные строки
Шаблонные литералы позволяют создавать многострочные строки без необходимости использования символов переноса строки (\n).
const multiLineString = `This is a string
that spans across
multiple lines.`;

console.log(multiLineString);
// Вывод:
// This is a string
// that spans across
// multiple lines.


🟠Встроенные выражения
Внутри шаблонных литералов можно использовать любые JavaScript-выражения.
const a = 5;
const b = 10;

const result = `The sum of ${a} and ${b} is ${a + b}.`;

console.log(result);
// Вывод: The sum of 5 and 10 is 15.


🟠Вызов функций внутри шаблонных литералов
Можно вызывать функции и методы внутри шаблонных литералов.
function toUpperCase(str) {
return str.toUpperCase();
}

const name = 'Alice';

const loudGreeting = `Hello, ${toUpperCase(name)}!`;

console.log(loudGreeting);
// Вывод: Hello, ALICE!


🟠Тегированные шаблонные литералы
Тегированные шаблонные литералы позволяют обработать строку с помощью функции перед ее окончательной интерпретацией.
function tag(strings, ...values) {
console.log(strings);
console.log(values);
return 'Tagged template';
}

const name = 'Alice';
const age = 25;

const taggedResult = tag`Name: ${name}, Age: ${age}`;

console.log(taggedResult);
// Вывод:
// [ 'Name: ', ', Age: ', '' ]
// [ 'Alice', 25 ]
// Tagged template


Ставь 👍 и забирай 📚 Базу знаний
👍10
🤔 Как заредиректить пользователя на URL?

Можно изменить свойство, отвечающее за текущий адрес страницы, или вызвать метод, который вызывает загрузку другого URL. Это работает как обычный переход по ссылке.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍4
🤔 Зачем нам разбивать приложение отдельно на backend и frontend?

Разделение на Frontend (клиент) и Backend (сервер) – это стандартный подход в современной веб-разработке. Это делает приложение гибче, масштабируемее и удобнее в разработке.

🚩Почему лучше разделять?

🟠Гибкость и масштабируемость
Можно менять Frontend и Backend независимо.
Можно использовать разные технологии (например, Vue.js + Django).
Можно легко разделить команды разработчиков.

🟠Повышенная безопасность
Frontend не имеет доступа к базе данных.
Все важные вычисления, авторизация, хранение данных происходят на сервере.
API можно защитить токенами (JWT, OAuth).

🟠Уменьшение нагрузки на клиент
Логика обработки данных выполняется на сервере.
Клиент получает уже готовые данные, а не загружает огромные файлы.

🟠Легче разрабатывать и тестировать
Можно разрабатывать Frontend и Backend независимо.
Можно подменять сервер на mock-данные во время разработки.

🚩Как они общаются? (REST API & GraphQL)
Разделённые приложения общаются через API:
REST API (GET, POST, PUT, DELETE)
GraphQL API (запросы только нужных данных)
WebSockets (реальное время, чаты, онлайн-игры)
GET https://api.example.com/users


Ответ от Backend
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]


Ставь 👍 и забирай 📚 Базу знаний
👍5
🤔 Какие есть способы модификации цвета?

Можно изменить прозрачность, использовать фильтры, градиенты, наложения и тени. Также можно программно управлять цветом, меняя его тон, насыщенность, яркость через функции препроцессоров или CSS-функции.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥2
🤔 Зачем нужен eslint?

ESLint – это инструмент для автоматического анализа и исправления кода в JavaScript и TypeScript. Он помогает разработчикам следовать единым стилям кодирования, находить ошибки и предотвращать баги ещё до запуска кода.

🚩Почему ESLint полезен?
Без линтера код может быть неаккуратным и содержать ошибки, которые сложно отловить.

🚩Проблемы без ESLint

Разные стили написания кода
Пропущенные точки с запятой или лишние пробелы
Неиспользуемые переменные
Ошибки, которые не выявляются во время компиляции (например, undefined переменные)

🚩Решение с ESLint:

Автоматически находит ошибки и предупреждения
Подсказывает лучшие практики
Поддерживает кастомные правила
Работает в IDE и CI/CD (автоматическая проверка)

🟠Как ESLint работает?
ESLint использует набор правил, которые проверяют код. Если код нарушает эти правила – линтер выдаёт предупреждение или ошибку.
function sayHello(name) {
console.log("Hello, " + name)
}

sayHello("John")



Пример исправленного кода (ESLint fix)
function sayHello(name) {
console.log(`Hello, ${name}`);
}

sayHello("John");


🟠Как установить и настроить ESLint?
Установка
npm install eslint --save-dev


Создание конфига
npx eslint --init


Пример .eslintrc.js (настройки ESLint)
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
"eslint:recommended", // Базовые рекомендации
"plugin:vue/vue3-recommended" // Рекомендации для Vue
],
rules: {
"no-unused-vars": "warn", // Предупреждать о неиспользуемых переменных
"semi": ["error", "always"], // Обязательные точки с запятой
"quotes": ["error", "double"], // Только двойные кавычки
},
};


Запуск проверки кода
npx eslint myfile.js


Автоматическое исправление ошибок
npx eslint myfile.js --fix


🟠ESLint в IDE (VS Code, WebStorm)
Чтобы ESLint работал в VS Code, установите расширение ESLint и включите "editor.codeActionsOnSave"
"editor.codeActionsOnSave": {
"source.fixAll.eslint": true
}


🟠ESLint в CI/CD (автоматическая проверка на сервере)
В проектах ESLint можно запускать в GitHub Actions, Jenkins, GitLab CI и других CI/CD системах, чтобы не допускать ошибок в main ветку.
"scripts": {
"lint": "eslint src --fix"
}


Теперь перед коммитом можно запускать:
npm run lint


Ставь 👍 и забирай 📚 Базу знаний
👍3
🤔 Как принудительно обновить компонент во Vue?

Иногда Vue может не понять, что данные изменились. В таком случае можно заставить компонент перерисоваться. Один способ — изменить значение key у компонента, это заставит его перерисоваться заново. Также можно использовать локальное реактивное состояние, которое сбрасывается и снова включает компонент. В крайнем случае используют forceUpdate, но это плохая практика.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍5🔥1
Please open Telegram to view this post
VIEW IN TELEGRAM