Frontend | Вопросы собесов
18.7K subscribers
36 photos
2 videos
1.31K 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>
))}


Ставь 👍 и забирай 📚 Базу знаний
👍4💊3
🤔 Для чего используются ключи в JSX?

Ключи помогают React отслеживать элементы списка при рендере и обновлении. Они позволяют эффективно сравнивать текущую и новую версии списка и минимизировать DOM-операции.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍14🔥3
🤔 В чём преимущество синтаксического сахара в виде async await над promise?

Оба способа позволяют работать с асинхронным кодом в JavaScript, но async/await делает код чище, проще и удобнее.

🟠`async/await` проще читать и писать

Код на Promise.then() часто становится вложенным и запутанным
fetch("https://api.example.com/user")
.then(response => response.json())
.then(user => {
return fetch(`https://api.example.com/orders/${user.id}`);
})
.then(response => response.json())
.then(orders => {
console.log("Заказы:", orders);
})
.catch(error => console.error("Ошибка:", error));


Решение: async/await
async function getUserOrders() {
try {
const response = await fetch("https://api.example.com/user");
const user = await response.json();

const ordersResponse = await fetch(`https://api.example.com/orders/${user.id}`);
const orders = await ordersResponse.json();

console.log("Заказы:", orders);
} catch (error) {
console.error("Ошибка:", error);
}
}

getUserOrders();


async/await лучше обрабатывает ошибки
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => {
throw new Error("Ошибка в обработке данных");
})
.catch(error => console.error("Ошибка:", error));


async/await + try/catch – мощная обработка ошибок
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) throw new Error("Ошибка HTTP " + response.status);

const data = await response.json();
console.log(data);
} catch (error) {
console.error("Ошибка:", error);
}
}
fetchData();


async/await удобен в for и try/catch
const urls = ["url1", "url2", "url3"];
urls.forEach(url => {
fetch(url)
.then(response => response.json())
.then(data => console.log(data));
});


async/await в for of
async function fetchAll(urls) {
for (const url of urls) {
const response = await fetch(url);
const data = await response.json();
console.log(data);
}
}
fetchAll(["url1", "url2", "url3"]);


async/await работает с try/finally
async function fetchData() {
try {
console.log("Запрос данных...");
const response = await fetch("https://api.example.com");
const data = await response.json();
console.log("Данные:", data);
} catch (error) {
console.error("Ошибка:", error);
} finally {
console.log("Закрываем соединение...");
}
}
fetchData();


async/await можно использовать внутри Promise.all()
Иногда Promise.all() быстрее, потому что запускает промисы параллельно.
async function fetchMultiple() {
const [user, orders] = await Promise.all([
fetch("https://api.example.com/user").then(res => res.json()),
fetch("https://api.example.com/orders").then(res => res.json())
]);

console.log(user, orders);
}
fetchMultiple();


Ставь 👍 и забирай 📚 Базу знаний
👍8
🤔 Что такое DNS?

Это система доменных имен, которая преобразует читаемые человеком домены (например, example.com) в IP-адреса серверов.

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍18🔥9
🤔 Расскажи про области видимости

В 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); // "Я переменная из модуля"


Ставь 👍 и забирай 📚 Базу знаний
👍15🤔1
🤔 В чём разница между debugger и console.log?

- console.log — выводит данные в консоль, не прерывает выполнение.
- debugger — останавливает выполнение кода и открывает DevTools, позволяет пошагово отлаживать.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍13🔥2
🤔 Как можно вставить svg в html документ?

Вставить SVG в HTML можно несколькими способами, в зависимости от того, что вам нужно: просто отобразить изображение, стилизовать его через CSS или динамически изменять с помощью JavaScript.

🟠Прямой (inline) SVG-код в HTML
Этот способ позволяет стилизовать и изменять SVG с помощью CSS и JavaScript.
<svg width="100" height="100" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>


🟠Через тег `<img>`
Если SVG не нужно изменять, можно вставить его как обычное изображение.
<img src="image.svg" alt="Описание изображения" width="100" height="100">


🟠Через CSS `background-image`
SVG можно использовать как фоновое изображение.
<div class="icon"></div>

<style>
.icon {
width: 100px;
height: 100px;
background-image: url('image.svg');
background-size: cover;
}
</style>


🟠Через тег `<object>`
Позволяет загружать SVG-файлы и взаимодействовать с ними.
<object type="image/svg+xml" data="image.svg" width="100" height="100"></object>


🟠Через тег `<iframe>`
SVG можно загружать в iframe.
<iframe src="image.svg" width="100" height="100"></iframe>


Ставь 👍 и забирай 📚 Базу знаний
👍8
🤔 В чём отличия HTML5 от HTML4.01 и XHTML1.0?

- HTML5 поддерживает больше API и новых тегов;
- Он не требует строгой валидации и работает в "универсальном" режиме;
- HTML5 заменил множество устаревших элементов;
- XHTML1.0 требует строгий синтаксис и подаётся как XML;
- HTML4.01 ограничен в функциональности, не поддерживает современные API.


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

Делегирование событий (Event Delegation) — это техника, при которой мы не навешиваем обработчик на каждый элемент, а ставим один обработчик на родителя и отслеживаем события его потомков.

🚩Как работает делегирование?

Обычный способ (без делегирования)
Если у нас есть 10 кнопок, мы можем повесить обработчик на каждую
document.querySelectorAll("button").forEach((btn) => {
btn.addEventListener("click", () => {
console.log("Кнопка нажата");
});
});


Если кнопок 1000, это создаст 1000 обработчиков, что неэффективно.
Если кнопки добавляются динамически (например, из API), обработчик на новые кнопки не сработает.

🟠Делегирование событий (оптимальный способ)
Вместо того чтобы вешать обработчик на каждую кнопку, ставим один обработчик на родительский элемент и проверяем, кто вызвал событие:
document.getElementById("container").addEventListener("click", (event) => {
if (event.target.tagName === "BUTTON") {
console.log("Кнопка нажата:", event.target.textContent);
}
});


🟠Пример с динамическими элементами
Если мы добавляем кнопки динамически, обработчик все равно будет работать
document.getElementById("container").addEventListener("click", (event) => {
if (event.target.classList.contains("btn")) {
console.log("Нажата кнопка:", event.target.textContent);
}
});

// Добавляем новую кнопку динамически
setTimeout(() => {
const newButton = document.createElement("button");
newButton.classList.add("btn");
newButton.textContent = "Новая кнопка";
document.getElementById("container").appendChild(newButton);
}, 2000);


Ставь 👍 и забирай 📚 Базу знаний
👍10🔥1
🤔 Какие статусы есть у Promise?

- pending — в процессе, ещё не завершён;
- fulfilled — успешно завершён (вызван resolve);
- rejected — завершён с ошибкой (вызван reject).


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
👍9
🤔 С помощью чего можно рассчитать идентификатор в js?

В JavaScript есть несколько способов сгенерировать уникальный идентификатор (ID), в зависимости от требований:

🟠 Генерация UUID
UUID (универсально уникальный идентификатор) – это 128-битное число, представленное строкой в формате xxxxxxxx-xxxx-Mxxx-Nxxx-xxxxxxxxxxxx.
Генерация с помощью crypto.randomUUID() (современный способ)
const id = crypto.randomUUID();
console.log(id); // Например: "3d593c8e-7a34-45f7-9a14-2f5f5788d4ec"


Использование библиотеки uuid
import { v4 as uuidv4 } from 'uuid';

const id = uuidv4();
console.log(id); // "f47ac10b-58cc-4372-a567-0e02b2c3d479"


🟠Хеш-функции (SHA, MD5)
Если нужно вычислить уникальный идентификатор на основе входных данных (например, строки или объекта), можно использовать хеш-функции.
SHA-256 через crypto.subtle
async function generateHash(input) {
const encoder = new TextEncoder();
const data = encoder.encode(input);
const hashBuffer = await crypto.subtle.digest('SHA-256', data);
return [...new Uint8Array(hashBuffer)].map(b => b.toString(16).padStart(2, '0')).join('');
}

generateHash("hello").then(console.log);
// Например: "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"


🟠Генерация случайного идентификатора
Если нужна просто случайная строка, можно использовать Math.random().
Базовая генерация ID
const id = Math.random().toString(36).substring(2, 10);
console.log(id); // Например: "5g7f8a1z"


Более безопасный вариант с crypto.getRandomValues()
function generateRandomId(length = 16) {
const array = new Uint8Array(length);
crypto.getRandomValues(array);
return [...array].map(b => b.toString(16).padStart(2, '0')).join('');
}

console.log(generateRandomId(8)); // Например: "a3f9b8c7"


🟠Инкрементальные ID
Если нужно просто увеличивающееся число (например, ID для записей в массиве), можно использовать счётчик
let counter = 0;
function generateIncrementalId() {
return ++counter;
}

console.log(generateIncrementalId()); // 1
console.log(generateIncrementalId()); // 2
console.log(generateIncrementalId()); // 3


🟠Хеширование строки (например, объекта)
Можно создать ID, основываясь на JSON-объекте.
function hashObject(obj) {
return JSON.stringify(obj)
.split("")
.reduce((hash, char) => {
return ((hash << 5) - hash) + char.charCodeAt(0);
}, 0)
.toString(16);
}

console.log(hashObject({ name: "Alice", age: 25 })); // Например: "-3d4e5f"


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

Плюсы:
- Меньше шаблонного кода — изменения происходят «автоматически» благодаря реактивности.
- Простота обучения, ближе к привычному JS-подходу.
- Более высокая производительность при грамотном применении (
@observer).
- Подходит для средних и больших проектов без сложного boilerplate.
Минусы:
- Магия — сложнее отследить, что и где меняется, особенно для новых участников команды.
- Может вызывать лишние перерендеры, если неправильно использовать observable.
- Меньшая распространённость по сравнению с Redux — меньше обучающих материалов и tooling.


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

Если пользователи захотят распечатать вашу веб-страницу, важно, чтобы она выглядела чисто и профессионально. Для этого используется CSS-медиа-правило @media print, которое позволяет задать специальные стили для печати.

🟠Использование `@media print`
Вы можете задать стили, которые будут применяться только при печати
@media print {
body {
font-size: 12pt; /* Оптимальный размер шрифта */
color: black; /* Убираем цветной текст для экономии чернил */
background: none !important; /* Убираем фон */
}
}


🟠Убираем ненужные элементы (меню, рекламу, анимации)
Некоторые элементы (например, навигация, футер, кнопки) не нужны при печати, их можно скрыть
@media print {
nav, .sidebar, .ads, .button {
display: none; /* Скрываем ненужное */
}
}


🟠Изменяем ширину страницы и текст
Обычно страницы шире, чем лист бумаги. Можно задать max-width для удобства
@media print {
body {
width: 100%;
max-width: 800px; /* Уменьшаем ширину */
margin: auto; /* Центрируем */
}
}


Заменяем цвета на чёрно-белые (экономия чернил)
@media print {
a {
color: black !important; /* Делаем ссылки чёрными */
text-decoration: underline; /* Добавляем подчёркивание */
}
}


🟠Добавляем URL ссылок в текст
При печати гиперссылки не работают, поэтому можно показать их адрес
@media print {
a::after {
content: " (" attr(href) ")"; /* Добавляем URL рядом со ссылкой */
font-size: 10pt;
color: gray;
}
}


Избегаем разрывов страниц в неудобных местах
@media print {
h1, h2, h3 {
page-break-after: avoid; /* Не разрываем страницу после заголовка */
}
p {
page-break-inside: avoid; /* Не разрываем абзац на две страницы */
}
}


Ставь 👍 и забирай 📚 Базу знаний
👍9
🤔 Как защитить cookie от JS?

При установке cookie нужно использовать флаг HttpOnly, чтобы JavaScript не имел к ним доступа. Также полезны флаги Secure (только по HTTPS) и SameSite (ограничение кросс-доступа).

Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥11👍2
🤔 Как работают плавающие элементы (floats)?

float – это CSS-свойство, которое позволяет "выплывать" элементу из обычного потока документа и обтекаться другими элементами (например, текстом).

Основные значения float
<img src="image.jpg" class="float-img">
<p>Это текст, который будет обтекать картинку.</p>

.float-img {
float: left;
margin-right: 10px;
}


🟠Почему родитель "схлопывается" при `float`?
Когда внутри div есть только float-элементы, браузер считает, что он пустой, потому что float убирает элемент из потока.
<div class="container">
<img src="image.jpg" class="float-img">
<p>Текст обтекает картинку.</p>
</div>

.container {
background: lightgray;
}
.float-img {
float: left;
}


Решение 1: overflow: hidden;
.container {
overflow: hidden; /* Контейнер теперь учитывает float-элементы */
}


Решение 2: clearfix (старый способ)
.container::after {
content: "";
display: block;
clear: both;
}


🟠Как остановить обтекание (`clear`)?
Чтобы отменить обтекание, используется clear.
<img src="image.jpg" class="float-img">
<p>Этот текст обтекает картинку.</p>
<div class="clear"></div>
<p>Этот текст пойдёт на новую строку.</p>

.float-img {
float: left;
margin-right: 10px;
}
.clear {
clear: both;
}


🚩Почему `float` устарел и что использовать вместо него?
Раньше float использовали для создания колонок и сеток, но сегодня его заменили:
Flexbox (display: flex;) – лучше для адаптивных макетов.
CSS Grid (display: grid;) – мощный инструмент для сложных сеток.
.container {
display: flex;
align-items: center;
}


Ставь 👍 и забирай 📚 Базу знаний
👍8
🤔 Какие методы общения имеются в протоколе HTTP?

- GET — получение данных;
- POST — отправка/создание;
- PUT — обновление;
- PATCH — частичное обновление;
- DELETE — удаление;
- OPTIONS, HEAD, CONNECT, TRACE — вспомогательные методы.


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

Dependency Injection (DI) – это паттерн проектирования, который помогает разделять зависимости и делает код гибче, тестируемее и поддерживаемее. Вместо того чтобы создавать зависимости внутри класса, они передаются (инъектируются) извне.

🚩Почему DI полезен?

🟠Уменьшает связность кода (Loose Coupling)
Вместо того чтобы жестко привязывать один модуль к другому, DI передает зависимости снаружи.
class UserService {
constructor() {
this.db = new Database(); // Прямо создаем зависимость
}

getUser(id) {
return this.db.findUserById(id);
}
}


С DI (гибкость)
class UserService {
constructor(db) {
this.db = db; // DI передает зависимость извне
}

getUser(id) {
return this.db.findUserById(id);
}
}

// Передаем нужную зависимость
const database = new Database();
const userService = new UserService(database);


🟠Улучшает тестируемость (Unit-тесты проще)
С DI можно подменять зависимости на заглушки (mock, fake, stub).
const userService = new UserService(); // Всегда использует реальную Database
userService.getUser(1); // Как протестировать без реальной БД? 🤔


С DI (можно подменить зависимость)
class FakeDatabase {
findUserById(id) {
return { id, name: "Тестовый пользователь" };
}
}

const fakeDb = new FakeDatabase();
const userService = new UserService(fakeDb);

console.log(userService.getUser(1)); // Тест без реальной БД


🟠Улучшает расширяемость (легко менять зависимости)
Допустим, сначала использовали MySQLDatabase, но решили перейти на MongoDatabase.
class UserService {
constructor() {
this.db = new MySQLDatabase(); // Нужно менять здесь
}
}


С DI (добавляем новую зависимость без изменения кода UserService)
const db = new MongoDatabase(); // Просто передаем другую зависимость
const userService = new UserService(db);


🟠Упрощает управление зависимостями (через DI-контейнеры)
В крупных приложениях удобно использовать DI-контейнер (например, InversifyJS для JavaScript/TypeScript).
import "reflect-metadata";
import { Container, injectable, inject } from "inversify";

@injectable()
class Database {
findUserById(id) {
return { id, name: "База данных" };
}
}

@injectable()
class UserService {
constructor(@inject(Database) db) {
this.db = db;
}

getUser(id) {
return this.db.findUserById(id);
}
}

// Настраиваем DI-контейнер
const container = new Container();
container.bind(Database).toSelf();
container.bind(UserService).toSelf();

// Получаем объект с нужными зависимостями
const userService = container.get(UserService);
console.log(userService.getUser(1));


Ставь 👍 и забирай 📚 Базу знаний
👍10
🤔 В каком случае важен порядок: при копировании объекта или массива?

- Для массива порядок важен всегда, так как позиции имеют смысл (это индексированная структура).
- Для объекта порядок чаще не имеет значения, но в некоторых случаях (например, при сериализации) он может быть важен, особенно если зависит от порядка вставки.


Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
🔥5👍3