Frontend | Вопросы собесов
19.3K subscribers
33 photos
3 videos
909 links
Сайт easyoffer.ru
Реклама @easyoffer_adv
ВП @easyoffer_vp

Тесты t.me/+T0COHtFzCJkwMDUy
Задачи t.me/+_tcX2w2EmvdmMTgy
Вакансии t.me/+CgCAzIyGHHg0Nzky
Download Telegram
🤔 Расскажи про оптимизацию рендеринга в react?

Это процесс снижения количества лишних перерисовок компонентов, что улучшает производительность приложения. React повторно рендерит компоненты, когда их состояние (state) или свойства (props) изменяются. Однако часто это приводит к ненужным рендерам, которые можно избежать.

🚩Почему важна оптимизация рендеринга?

🟠Производительность
Чем больше компонентов рендерится без необходимости, тем больше времени тратится на вычисления и обновления DOM.
🟠Экономия ресурсов
Избегая лишних рендеров, приложение работает быстрее, а пользовательский интерфейс становится более отзывчивым.
🟠Лучший UX
Плавная работа интерфейса критична для сложных приложений с большим количеством данных.

🚩Основные подходы к оптимизации рендеринга

🟠Мемоизация компонентов
React предоставляет утилиту React.memo, чтобы предотвращать ререндеринг компонента, если его props не изменились.
import React from 'react';

const MyComponent = React.memo(({ count }) => {
console.log('Рендер компонента');
return <div>Счётчик: {count}</div>;
});

// Использование
export default function App() {
const [count, setCount] = React.useState(0);

return (
<div>
<MyComponent count={count} />
<button onClick={() => setCount(count + 1)}>Увеличить</button>
</div>
);
}


🟠Использование `useMemo` и `useCallback`
Эти хуки используются для предотвращения повторных вычислений и создания функций при каждом рендере.
import React, { useMemo } from 'react';

function ExpensiveCalculationComponent({ number }) {
const calculatedValue = useMemo(() => {
console.log('Выполняются сложные вычисления...');
return number ** 2;
}, [number]); // Пересчитывается только если `number` изменился

return <div>Результат: {calculatedValue}</div>;
}


Пример useCallback
import React, { useCallback, useState } from 'react';

const Child = React.memo(({ onClick }) => {
console.log('Рендер дочернего компонента');
return <button onClick={onClick}>Кликни меня</button>;
});

function Parent() {
const [count, setCount] = useState(0);

const handleClick = useCallback(() => {
console.log('Кнопка нажата');
}, []); // Создаётся одна и та же функция между рендерами

return (
<div>
<Child onClick={handleClick} />
<button onClick={() => setCount(count + 1)}>Увеличить {count}</button>
</div>
);
}


🟠Разделение кода и ленивый рендеринг
Использование React.lazy и Suspense позволяет загружать компоненты только тогда, когда они необходимы.
import React, { Suspense } from 'react';

const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
return (
<Suspense fallback={<div>Загрузка...</div>}>
<LazyComponent />
</Suspense>
);
}


🟠Проверка зависимости в `useEffect`
Избегайте запуска побочных эффектов, если зависимости не изменились.
React.useEffect(() => {
console.log('Эффект сработал!');
}, [/* следите только за нужными зависимостями */]);


🟠Избегайте анонимных функций и объектов в `props`
Передача новых объектов и функций через props вызывает лишние рендеры.
<ChildComponent data={{ key: 'value' }} />


Лучше так
const data = { key: 'value' };
<ChildComponent data={data} />;


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

🟠Использование ключей при рендере списков
Каждый элемент списка должен иметь уникальный ключ, чтобы React мог правильно отслеживать изменения.
{items.map(item => (
<div key={item.id}>{item.name}</div>
))}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10💊2
🤔 Что такое GRASP?

GRASP (General Responsibility Assignment Software Patterns) — это набор паттернов для правильного распределения ответственности между классами: контроллер, эксперт, низкая связность, высокая связность, полиморфизм и др.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11
🤔 Какие есть проблемы у di?

Dependency Injection (DI) — это паттерн, который упрощает управление зависимостями, но у него есть свои сложности и недостатки.

🟠Усложнение кода и архитектуры
При использовании DI код может стать излишне сложным, особенно если внедрение зависимостей реализуется вручную или через сложные контейнеры.
class Service {
constructor(repository) {
this.repository = repository;
}
}


🟠Производительность (затраты на создание объектов)
Если DI используется через контейнеры, они могут замедлять выполнение программы, так как:
Создание объектов может занимать больше времени (особенно при ленивой инициализации).
Поиск зависимостей в контейнере тоже требует времени.
В Angular, NestJS и других фреймворках DI может потреблять больше ресурсов, чем обычное создание объектов.

🟠Скрытая сложность и магия
Когда зависимости внедряются автоматически через контейнер, код становится менее очевидным.
@Injectable()
class Service {
constructor(private readonly repository: Repository) {}
}


🟠Проблемы с тестированием
Хотя DI часто называют удобным для тестирования, на практике могут возникнуть сложности:
Если контейнер создаёт объекты динамически, тесты могут работать нестабильно.
Нужно явно мокать зависимости, что может усложнять настройку тестов.
class Service {
constructor(repository) {
this.repository = repository;
}
}

const service = new Service(new Repository()); // Проблема при тестировании – жестко задана зависимость


Здесь тестировать Service сложно, потому что Repository создаётся вручную. Приходится использовать мок-объекты
const mockRepository = { getData: () => "mock data" };
const service = new Service(mockRepository);


🟠DI не всегда нужен
В маленьких проектах использование DI может быть излишним. Простое создание объектов может быть проще и понятнее, чем настройка DI-контейнера.
const repository = new Repository();
const service = new Service(repository);


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1
🤔 Как можно запретить изменение объекта?

Для этого используется механизм, который делает объект неизменяемым: его свойства становятся недоступны для модификации, добавления или удаления. Это полезно, когда необходимо сохранить объект в первоначальном виде, особенно при работе с конфигурацией или в функциональном программировании, где важна неизменяемость состояния.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
💊27🤔15
🤔 Как достигается изоляция при использовании бэм?

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

🚩Как БЭМ предотвращает конфликты?

🟠Все стили зависят только от конкретного блока
В БЭМ нет зависимостей от родительских элементов, поэтому стили блока не сломаются, если он окажется в другом месте.
<div class="button">Кнопка</div>

.button {
background: blue;
color: white;
}


Плохой пример без БЭМ
.container .button {
background: blue;
}


🟠Элементы (`__`) зависят только от своего блока
Стили элемента никогда не зависят от родителя — только от блока.
<div class="card">
<h2 class="card__title">Заголовок</h2>
<p class="card__text">Текст карточки</p>
</div>

.card__title {
font-size: 20px;
}

.card__text {
color: gray;
}


🟠Модификаторы (`--`) изменяют только нужные стили
Модификаторы позволяют изменять внешний вид без переписывания базовых стилей.
<button class="button button--red">Кнопка</button>
<button class="button button--blue">Кнопка</button>

.button {
padding: 10px;
border-radius: 5px;
}

.button--red {
background: red;
}

.button--blue {
background: blue;
}


🟠Имена классов уникальны, нет глобальных стилей
В БЭМ не используется tag {} или id {} — только классы. Это предотвращает конфликты стилей.
h1 {
color: red;
}


БЭМ-версия
.card__title {
color: red;
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16💊2
🤔 В чём отличие адаптивного дизайна от отзывчивого?

Адаптивный дизайн — фиксированные точки перехода под устройства (320px, 768px и т.д.).
Отзывчивый (responsive) — гибкий, использует проценты, vh, vw, flex, grid, и подстраивается плавно под любое разрешение.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥7
🤔 Какие особенности слежения за "глубокими" объектами?

Когда мы отслеживаем изменения в объектах (например, в React, Vue или MobX), важно понимать, что JavaScript не умеет автоматически следить за вложенными свойствами. Это называется глубокое слежение (deep watching).

Проблема: поверхностное слежение (`shallow watching`)

JavaScript сравнивает только ссылки на объекты, а не их содержимое.
const obj = { user: { name: "Иван" } };
const copy = obj;

copy.user.name = "Петр";
console.log(obj.user.name); // "Петр" (оба объекта ссылаются на одно и то же)


🚩Глубокое копирование vs поверхностное

Обычный Object.assign() или spread-оператор ({ ...obj }) делают поверхностное копирование:
const obj = { user: { name: "Иван" } };
const shallowCopy = { ...obj };

shallowCopy.user.name = "Петр";
console.log(obj.user.name); // "Петр" 😱 (изменился оригинал!)


Для глубокого копирования можно использовать structuredClone() или JSON.parse(JSON.stringify(obj)):
const deepCopy = structuredClone(obj);
deepCopy.user.name = "Петр";

console.log(obj.user.name); // "Иван" (оригинал не изменился)


🚩Как следить за глубокими объектами?

🟠React: следим через `useState` и `useEffect`
В React состояние обновляется только при изменении ссылки (shallow compare).
const [user, setUser] = useState({ name: "Иван" });

useEffect(() => {
console.log("Имя изменилось:", user.name);
}, [user]); // Работает только если user — новый объект!

// НЕ сработает:
user.name = "Петр"; // user остался тем же объектом


Решение – создавать новый объект при изменении:
setUser(prev => ({ ...prev, name: "Петр" }));


🟠Vue: `watch` vs `watchEffect` (глубокое слежение)

Обычный watch следит только за первой вложенностью
watch(user, (newValue) => {
console.log("Изменено:", newValue);
});


Глубокое слежение (deep: true)
watch(user, (newValue) => {
console.log("Изменено:", newValue);
}, { deep: true });


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10💊1
🤔 Как найти все скрытые элементы на странице?

Через JS:
document.querySelectorAll('[hidden], [style*="display: none"], [style*="visibility: hidden"]')
Можно также использовать getComputedStyle(el).display === "none".


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🔥9
🤔 Как мы будем через js анимировать что либо?

В JavaScript есть три основных способа создания анимаций:

CSS-анимации (transition, @keyframes) + изменение классов через JS
Метод requestAnimationFrame()
Использование библиотек (GSAP, Anime.js, Velocity.js)

🟠CSS-анимации + управление через JS
Самый простой способ — использовать CSS-анимации, а в JS только добавлять или убирать классы.
<button onclick="toggleBox()">Анимировать</button>
<div id="box"></div>

<style>
#box {
width: 100px;
height: 100px;
background: red;
transition: transform 0.5s ease-in-out;
}
.move {
transform: translateX(200px);
}
</style>

<script>
function toggleBox() {
document.getElementById("box").classList.toggle("move");
}
</script>


🟠`requestAnimationFrame()` — лучший способ в чистом JS
Если нужно более гибкое управление анимацией, используем requestAnimationFrame().
<button onclick="startAnimation()">Старт</button>
<div id="box"></div>

<style>
#box {
width: 50px;
height: 50px;
background: blue;
position: absolute;
}
</style>

<script>
let position = 0;
let animationId;

function animate() {
position += 5; // Двигаем на 5px за кадр
document.getElementById("box").style.transform = `translateX(${position}px)`;

if (position < 300) { // Останавливаем, когда достигнет 300px
animationId = requestAnimationFrame(animate);
}
}

function startAnimation() {
cancelAnimationFrame(animationId); // Останавливаем предыдущую анимацию
position = 0;
animate();
}
</script>


🟠Библиотеки (GSAP, Anime.js, Velocity.js)
Если нужно делать мощные анимации с минимальным кодом, лучше использовать библиотеку.
<button onclick="animateBox()">Анимировать</button>
<div id="box"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>

<script>
function animateBox() {
gsap.to("#box", { x: 300, rotation: 360, duration: 2, ease: "elastic.out(1,0.3)" });
}
</script>


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🔥2🤔1💊1
🤔 Зачем нужен use strict?

use strict вводит строгий режим:
- предотвращает использование необъявленных переменных;
- запрещает удаление переменных;
- помогает находить ошибки на ранних этапах.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥3
🤔 Что делает omit?

omit – это функция, которая удаляет указанные ключи из объекта и возвращает новый объект без этих ключей.

В JavaScript нет встроенного omit, но его можно реализовать с помощью деструктуризации и методов Object.fromEntries() или reduce().

Реализация omit с Object.fromEntries() (современный способ)
function omit(obj, keys) {
return Object.fromEntries(
Object.entries(obj).filter(([key]) => !keys.includes(key))
);
}

const user = { name: "Alice", age: 25, password: "123456" };
const safeUser = omit(user, ["password"]);

console.log(safeUser); // { name: "Alice", age: 25 }


Реализация omit с reduce() (альтернативный способ)
function omit(obj, keys) {
return Object.keys(obj).reduce((acc, key) => {
if (!keys.includes(key)) acc[key] = obj[key];
return acc;
}, {});
}

const data = { a: 1, b: 2, c: 3 };
console.log(omit(data, ["b"])); // { a: 1, c: 3 }


Если используете Lodash, можно просто вызвать
import { omit } from "lodash";

const user = { name: "Alice", age: 25, password: "123456" };
const safeUser = omit(user, ["password"]);

console.log(safeUser); // { name: "Alice", age: 25 }


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥3
🤔 Что известно про методологию Mobile First?

Mobile First — подход, при котором:
- Сначала создаётся макет для маленьких экранов;
- Далее — добавляются стили через медиа-запросы для больших экранов (
@media (min-width: ...));
- Улучшает производительность и приоритет UX на мобильных.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
🤔 Какие есть значения у box-sizing?

Свойство box-sizing в CSS управляет тем, как рассчитываются размеры элемента, включая ширину и высоту. Оно определяет, включаются ли в эти размеры внутренние отступы (padding) и границы (border), или же они добавляются отдельно.

🚩Возможные значения `box-sizing`

🟠`content-box`
Размеры элемента считаются только по `width` и `height`, без учета padding и border. Если добавить padding или border, фактические размеры элемента увеличатся.
   .box {
width: 200px;
height: 100px;
padding: 20px;
border: 10px solid black;
box-sizing: content-box;
}


🟠`border-box`
width и height включают padding и border. Внутреннее содержимое (content) будет автоматически уменьшаться, чтобы уложиться в заданные размеры.
   .box {
width: 200px;
height: 100px;
padding: 20px;
border: 10px solid black;
box-sizing: border-box;
}


🟠`inherit`
Наследует значение box-sizing от родительского элемента.
   .parent {
box-sizing: border-box;
}
.child {
box-sizing: inherit; /* Унаследует border-box */
}


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
🤔 Для чего нужен хук useContext?

useContext позволяет доступаться к данным из контекста, не передавая их через props вручную.
Контекст используют, когда какие-то данные нужны многим компонентам на разных уровнях вложенности (например, тема, язык, авторизация). Вместо "протягивания" props через несколько уровней, компонент просто берёт нужное значение из контекста.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥7💊2
🤔 Как браузер понимает что ресурс нужно закешировать?

Браузер использует HTTP-заголовки и механизмы кэширования, чтобы решить, нужно ли сохранять ресурс (HTML, CSS, JS, изображения) и как долго его хранить.

🚩Как браузер решает, кешировать ресурс или нет?

Когда браузер загружает ресурс, сервер может сказать браузеру, как его кешировать, с помощью HTTP-заголовков.
HTTP/1.1 200 OK
Cache-Control: max-age=3600, public
ETag: "abc123"


🚩Как работают заголовки кэширования?

🟠`Cache-Control` – главный заголовок
Определяет, как долго ресурс должен храниться в кэше.
Cache-Control: max-age=86400, public


🟠`Expires` – устаревший, но ещё используется
Определяет конкретную дату, до которой браузер может использовать кэшированный ресурс.
Expires: Wed, 26 Feb 2025 12:00:00 GMT


🟠`ETag` – проверка обновлений ресурса
Позволяет браузеру узнать, изменился ли файл на сервере.
ETag: "abc123"


Если браузер снова запрашивает ресурс, он отправляет заголовок
If-None-Match: "abc123"


🟠`Last-Modified` – альтернатива `ETag`
Дата последнего изменения ресурса.
Last-Modified: Tue, 25 Feb 2025 15:30:00 GMT


Браузер может отправить запрос с
If-Modified-Since: Tue, 25 Feb 2025 15:30:00 GMT


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🤔1
🤔 Как отменить обтекание картинки текстом?

Используется свойство clear, которое говорит элементу не обтекать плавающие элементы. Можно применить clear: both или вставить блок с этим стилем после float-элемента.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥3
🤔 Расскажи про области видимости

В JavaScript область видимости (scope) определяет доступность переменных, функций и объектов в разных частях кода. Это фундаментальная концепция, которая управляет тем, какие данные могут быть доступны или недоступны в различных частях программы.

🚩Глобальная область видимости

Переменные и функции, объявленные вне любых функций или блоков, находятся в глобальной области видимости. Они доступны из любой части программы.
var globalVar = 'Я глобальная переменная';

function testFunction() {
console.log(globalVar); // Доступно
}

testFunction();
console.log(globalVar); // Доступно


🚩Функциональная область видимости

Переменные, объявленные с помощью var внутри функции, имеют область видимости, ограниченную этой функцией. Они недоступны за её пределами.
function testFunction() {
var functionVar = 'Я внутри функции';
console.log(functionVar); // Доступно
}

testFunction();
console.log(functionVar); // Ошибка: переменная functionVar недоступна


🚩Блочная область видимости

Переменные, объявленные с помощью let и const, имеют область видимости, ограниченную ближайшим блоком {}.
if (true) {
let blockVar = 'Я внутри блока';
console.log(blockVar); // Доступно
}

console.log(blockVar); // Ошибка: переменная blockVar недоступна


🚩Область видимости модуля (Module Scope)

При использовании модулей (например, import и export в ES6), все переменные и функции в модуле имеют собственную область видимости. Они не попадают в глобальную область видимости.
export const myVar = 'Я переменная из модуля';


import { myVar } from './module1.js';
console.log(myVar); // "Я переменная из модуля"


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17💊5
🤔 Как стилизовать SVG?

SVG можно стилизовать тремя основными способами:
1. Через CSS: Указываются свойства fill, stroke, width, height и т. д. Применимо, если SVG встроен в HTML как элемент.
2. Через атрибуты SVG: Внутри тега <svg> и его вложенных элементов можно задать стили напрямую — например, fill="red" или stroke="black".
3. Через inline-стили: Добавляются через style="..." в самом теге SVG.
Важно помнить, что стилизовать SVG, подключённый как <img src="..." />, невозможно через CSS — только если он встроен непосредственно в DOM.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥4💊1
🤔 Зачем нам разбивать приложение отдельно на 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" }
]


Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥1
🤔 Что происходит при встрече с тегами link, img, script во время формирования DOM-дерева?

- link — блокирует рендер до загрузки CSS.
- img — создаёт отложенную загрузку изображения.
- script:
- Без async и defer — блокирует парсинг HTML до полной загрузки и выполнения.
- С defer — выполняется после построения DOM.
- С async — загружается и выполняется параллельно, но не в определённом порядке.


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