Frontend | Вопросы собесов
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @sendme_ads
Ko'proq ko'rsatish📈 Telegram kanali Frontend | Вопросы собесов analitikasi
Frontend | Вопросы собесов (@easy_javascript_ru) Rus til segmentidagi kanali faol ishtirokchi. Hozirda hamjamiyat 17 296 obunachidan iborat bo'lib, Texnologiyalar & Aralashmalar toifasida 7 490-o'rinni va Rossiya mintaqasida 37 846-o'rinni egallagan.
📊 Auditoriya ko‘rsatkichlari va dinamika
невідомо sanasidan buyon loyiha tez o‘sib, 17 296 obunachiga ega bo‘ldi.
08 Noyabr, 2026 dagi oxirgi ma’lumotlarga ko‘ra kanal barqaror faollikka ega. Oxirgi 30 kunda obunachilar soni -302 ga, so‘nggi 24 soatda esa -8 ga o‘zgardi va umumiy qamrov yuqori darajada qolmoqda.
- Tasdiqlash holati: Tasdiqlanmagan
- Jalb etish (ER): Auditoriya o‘rtacha 6.03% darajada jalb etiladi. Nashrdan keyingi dastlabki 24 soatda kontent odatda umumiy obunachilar sonining 4.46% ini tashkil etuvchi reaksiyalarni to‘playdi.
- Post qamrovi: Har bir post o‘rtacha 1 043 marta ko‘riladi; birinchi sutkada odatda 771 ta ko‘rish yig‘iladi.
- Reaksiyalar va o‘zaro ta’sir: Auditoriya faol: har bir postga o‘rtacha 4 ta reaksiya keladi.
- Tematik yo‘nalishlar: Kontent ставь, браузер, html, border, flex kabi asosiy mavzularga jamlangan.
📝 Tavsif va kontent siyosati
Muallif resursni shaxsiy fikrni ifoda etish maydoni sifatida ta’riflaydi:
“Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy
Контакт для рекламы: @sendme_ads”
Yuqori yangilanish chastotasi (oxirgi ma’lumot 09 Noyabr, 2026 da olingan) sababli kanal doimo dolzarb va katta qamrovli bo‘lib qoladi. Analitika auditoriya kontent bilan faol hamkorlik qilishini, uni Texnologiyalar & Aralashmalar toifasidagi muhim ta’sir nuqtasiga aylantirishini ko‘rsatadi.
message в дочерний компонент.
Родительский компонент (ParentComponent.js):
import React from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const message = "Привет, дочерний компонент!";
return (
<div>
<h1>Родительский компонент</h1>
<ChildComponent message={message} />
</div>
);
}
export default ParentComponent;
Дочерний компонент (ChildComponent.js):
import React from 'react';
function ChildComponent(props) {
return (
<div>
<h2>Дочерний компонент</h2>
<p>{props.message}</p>
</div>
);
}
export default ChildComponent;
Пояснение
1️⃣В родительском компоненте `ParentComponent`:
✅Создаем переменную message, содержащую строку "Привет, дочерний компонент!".
✅В JSX разметке мы рендерим дочерний компонент ChildComponent, передавая ему пропс message со значением переменной message.
2️⃣В дочернем компоненте ChildComponent:
✅Принимаем пропс message через параметр props.
✅Используем props.message для отображения переданной строки внутри тега <p>.
Дополнительные примеры
Родительский компонент (ParentComponent.js):
import React from 'react';
import ChildComponent from './ChildComponent';
function ParentComponent() {
const user = {
name: "Иван",
age: 25
};
return (
<div>
<h1>Родительский компонент</h1>
<ChildComponent user={user} />
</div>
);
}
export default ParentComponent;
Дочерний компонент (ChildComponent.js):
import React from 'react';
function ChildComponent(props) {
return (
<div>
<h2>Дочерний компонент</h2>
<p>Имя: {props.user.name}</p>
<p>Возраст: {props.user.age}</p>
</div>
);
}
export default ChildComponent;
В React данные передаются из родительского компонента в дочерний с помощью пропсов. В родительском компоненте данные передаются дочернему компоненту через атрибуты JSX, а в дочернем компоненте эти данные принимаются и используются через объект props.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхlet sayHiMixin = {
sayHi() {
console.log(`Привет, ${this.name}`);
},
sayBye() {
console.log(`Пока, ${this.name}`);
}
};
class User {
constructor(name) {
this.name = name;
}
}
// Копируем методы sayHiMixin в User.prototype
Object.assign(User.prototype, sayHiMixin);
let user = new User("Вася");
user.sayHi(); // Привет, Вася
user.sayBye(); // Пока, Вася
В этом примере миксин sayHiMixin добавляет методы sayHi и sayBye к классу User.
Миксины в CSS (Sass/SCSS)
Обычно используются в препроцессорах, таких как Sass или Less. Миксины позволяют определять наборы стилей, которые можно повторно использовать в различных местах стилей.
@mixin border-radius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}
.box {
@include border-radius(10px);
width: 100px;
height: 100px;
background-color: lightblue;
}
В этом примере миксин border-radius определяет стили для создания скругленных углов. Затем он используется в классе .box для применения этих стилей.
Почему это важно?
✅Повторное использование кода: Миксины позволяют избежать дублирования кода, что упрощает его поддержку и уменьшает вероятность ошибок.
✅Организация кода: Миксины помогают организовать код, разделяя общую функциональность на логические блоки.
✅Удобство и гибкость: С миксинами легко добавлять или изменять функциональность, не затрагивая основные классы или стили.
Миксины — это способ повторного использования кода. Они позволяют добавлять общие методы и свойства к классам (в JavaScript) или повторно использовать наборы стилей.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхfunction fetchData(callback) {
setTimeout(() => {
callback('Data received');
}, 1000);
}
fetchData((data) => {
console.log(data); // 'Data received'
});
2️⃣Промисы (Promises)
Предоставляют более элегантный способ работы с асинхронным кодом, избегая "ад колбэков" (callback hell). Промис может находиться в одном из трёх состояний: ожидание (pending), выполнен (fulfilled) или отклонён (rejected).
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data received');
}, 1000);
});
}
fetchData()
.then((data) => {
console.log(data); // 'Data received'
})
.catch((error) => {
console.error(error);
});
3️⃣Асинхронные функции (Async/Await)
Это синтаксическая надстройка над промисами, которая позволяет писать асинхронный код так, как будто он синхронный, что делает его более читабельным и удобным.
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Data received');
}, 1000);
});
}
async function fetchAsyncData() {
try {
const data = await fetchData();
console.log(data); // 'Data received'
} catch (error) {
console.error(error);
}
}
fetchAsyncData();
4️⃣Асинхронные итераторы (Async Iterators) и генераторы (Generators)
Используются для обработки потоков данных асинхронно, что полезно, например, при чтении данных из сетевых запросов или файлов.
async function* asyncGenerator() {
let i = 0;
while (i < 3) {
yield new Promise((resolve) =>
setTimeout(() => resolve(i++), 1000)
);
}
}
(async () => {
for await (let value of asyncGenerator()) {
console.log(value); // 0, затем 1, затем 2 (с интервалом в 1 секунду)
}
})();
Почему это важно?
✅Управление асинхронностью: Все эти способы позволяют эффективно управлять асинхронными операциями, такими как сетевые запросы, таймеры и взаимодействие с базами данных.
✅Читаемость и поддерживаемость кода: Использование промисов и async/await делает код более читаемым и поддерживаемым по сравнению с колбэками, особенно в сложных сценариях.
✅Ошибки и обработка исключений: Промисы и async/await предоставляют удобные механизмы для обработки ошибок, что делает код более устойчивым и надёжным.
Основные способы работы с асинхронным кодом включают колбэки, промисы и async/await. Каждый из них предоставляет свои преимущества для управления асинхронными операциями, делая код более читабельным и удобным для поддержки.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхthis. Контекст может изменяться в зависимости от способа вызова функции. Рассмотрим основные случаи, когда контекст функции меняется:
1️⃣Вызов функции как метода объекта
Когда функция вызывается как метод объекта, контекст (this) ссылается на этот объект.
const obj = {
name: 'Alice',
greet: function() {
console.log(this.name);
}
};
obj.greet(); // 'Alice'
В этом примере this внутри функции greet ссылается на объект obj.
2️⃣Вызов функции без контекста (как обычная функция)
Когда функция вызывается как обычная функция (не как метод объекта), контекст (this) ссылается на глобальный объект (window в браузере или global в Node.js). В строгом режиме (strict mode) контекст будет undefined.
function globalFunction() {
console.log(this);
}
globalFunction(); // В нестрогом режиме: window (в браузере), в строгом режиме: undefined
3️⃣Вызов конструктора (с использованием new)
Когда функция вызывается с использованием ключевого слова new, она работает как конструктор, и контекст (this) ссылается на новый объект, созданный этой функцией.
function Person(name) {
this.name = name;
}
const person = new Person('Bob');
console.log(person.name); // 'Bob'
4️⃣Явное задание контекста с помощью call, apply и bind
Позволяют явно задать контекст (this) для функции.
✅`call`: вызывает функцию с указанным контекстом и аргументами.
✅`apply`: вызывает функцию с указанным контекстом и аргументами в виде массива.
✅`bind`: возвращает новую функцию, которая при вызове имеет указанный контекст.
Пример:
function greet() {
console.log(this.name);
}
const person1 = { name: 'Charlie' };
const person2 = { name: 'Dave' };
greet.call(person1); // 'Charlie'
greet.apply(person2); // 'Dave'
const boundGreet = greet.bind(person1);
boundGreet(); // 'Charlie'
5️⃣Стрелочные функции
Не имеют своего собственного контекста (this). Вместо этого они наследуют контекст из внешней функции, в которой были объявлены. Это поведение называется "лексическим this".
const obj = {
name: 'Eve',
greet: function() {
const arrowFunction = () => {
console.log(this.name);
};
arrowFunction();
}
};
obj.greet(); // 'Eve'
В этом примере this внутри стрелочной функции ссылается на объект obj, потому что стрелочная функция была объявлена внутри метода greet этого объекта.
6️⃣Методы как коллбеки
Когда методы объектов передаются как коллбеки, контекст может измениться. Это часто происходит, если метод используется вне контекста своего объекта.
const obj = {
name: 'Frank',
greet: function() {
console.log(this.name);
}
};
setTimeout(obj.greet, 1000); // undefined или ошибка, так как this ссылается на глобальный объект или undefined в строгом режиме
Чтобы сохранить контекст, можно использовать bind:
setTimeout(obj.greet.bind(obj), 1000); // 'Frank'
Функция меняет контекст (this) в зависимости от способа ее вызова. Контекст может быть объектом, если функция вызывается как метод; новым объектом, если функция вызывается как конструктор; глобальным объектом или undefined, если функция вызывается как обычная функция; явно заданным при использовании call, apply или bind; или унаследованным из внешней функции в случае стрелочных функций.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых...) используется для разворачивания (распространения) элементов массивов или свойств объектов. Он позволяет удобным образом копировать массивы и объекты, объединять их, передавать элементы массивов в функции и многое другое.
Примеры:
1️⃣Копирование массива
const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
console.log(copiedArray); // [1, 2, 3]
Используя оператор spread, мы создаем копию массива originalArray. Изменения в copiedArray не будут затрагивать originalArray.
2️⃣Объединение массивов
const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const mergedArray = [...array1, ...array2];
console.log(mergedArray); // [1, 2, 3, 4, 5, 6]
Оператор spread позволяет легко объединять несколько массивов в один.
3️⃣Копирование объекта
const originalObject = { a: 1, b: 2 };
const copiedObject = { ...originalObject };
console.log(copiedObject); // { a: 1, b: 2 }
С помощью оператора spread можно копировать свойства одного объекта в другой.
4️⃣Объединение объектов
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObject = { ...obj1, ...obj2 };
console.log(mergedObject); // { a: 1, b: 2, c: 3, d: 4 }
Оператор spread позволяет объединять несколько объектов в один.
5️⃣Передача элементов массива в качестве аргументов функции
const numbers = [1, 2, 3];
const sum = (a, b, c) => a + b + c;
console.log(sum(...numbers)); // 6
Здесь оператор spread используется для передачи элементов массива numbers в функцию sum в качестве отдельных аргументов.
Почему это важно?
✅Удобство и читаемость кода: Оператор spread упрощает код, делая его более читаемым и понятным.
✅Эффективность: Он позволяет легко манипулировать массивами и объектами без необходимости использования сложных методов и циклов.
✅Непрямое копирование: Оператор spread создает неглубокие копии (shallow copies) массивов и объектов, что предотвращает нежелательные изменения исходных данных.
Оператор spread (...) используется для разворачивания массивов и объектов, что позволяет легко копировать, объединять и передавать данные.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхtransform с функцией scale. Это позволяет изменять размер элемента, не влияя на его положение и соседние элементы, так как трансформация происходит в контексте самого элемента и не меняет его фактические размеры в документе.
Пример использования
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Увеличение при наведении</title>
<style>
.container {
display: flex;
gap: 10px;
}
.item {
width: 100px;
height: 100px;
background-color: lightblue;
text-align: center;
line-height: 100px;
transition: transform 0.3s;
}
.item:hover {
transform: scale(1.2); /* Увеличение размера при наведении */
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</body>
</html>
Объяснение
✅`transition: transform 0.3s;`: Это свойство добавляет плавный переход для любых изменений, связанных с трансформацией элемента. В данном случае, это применимо к изменению масштаба (transform: scale(1.2)), которое происходит при наведении.
✅`transform: scale(1.2);`: Эта строка кода увеличивает размер элемента на 20% при наведении (hover). Значение 1.2 означает увеличение на 20% по обеим осям (X и Y).
✅Контейнер с `display: flex;` иак увеличить в Используется для демонстрации того, что элементы остаются на своих местах и не сдвигаются при увеличении одного из них. gap добавляет пространство между элементами.
Почему это важно?
✅Эффективность пользовательского интерфейса: Увеличение элементов при наведении может служить для привлечения внимания пользователя или для улучшения взаимодействия, например, при работе с интерактивными элементами.
✅Стабильность макета: Применение трансформации с transform: scale позволяет изменять размер элемента без изменения его фактического размера и расположения в документе, что сохраняет стабильность макета и не нарушает расположение соседних элементов.
✅Плавные анимации: Использование transition делает анимацию плавной и приятной для глаз, улучшая общее восприятие интерфейса.
Чтобы увеличить элемент при наведении, не сдвигая соседние элементы, используйте CSS свойство transform: scale вместе с transition для плавного перехода.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхflex-wrap. Оно позволяет управлять тем, как элементы в контейнере flex будут обрабатываться, если они не помещаются в одну строку.
Значения свойства
✅`nowrap` (значение по умолчанию): Все элементы будут располагаться в одной строке, независимо от их количества и размера. Они могут выходить за пределы контейнера.
✅`wrap`: Элементы будут переноситься на новую строку, если они не помещаются в одну.
✅`wrap-reverse`: Элементы также будут переноситься на новую строку, но строки будут расположены в обратном порядке.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример flex-wrap</title>
<style>
.container {
display: flex;
flex-wrap: wrap; /* Применение flex-wrap */
width: 300px;
border: 2px solid black;
}
.item {
flex: 1 1 100px;
margin: 5px;
background-color: lightblue;
text-align: center;
padding: 20px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
</div>
</body>
</html>
В этом примере контейнер .container имеет свойство flex-wrap: wrap, что позволяет элементам .item переноситься на новую строку, если они не помещаются в одну. Контейнер имеет фиксированную ширину 300px, поэтому элементы автоматически переносятся на следующую строку, когда их суммарная ширина превышает эту ширину.
Почему это важно?
✅Адаптивный дизайн: Свойство flex-wrap делает контейнер гибким, что особенно важно для адаптивного дизайна, когда элементы должны корректно отображаться на различных устройствах и экранах.
✅Управление пространством: Оно позволяет лучше управлять пространством внутри контейнера, предотвращая переполнение и выход элементов за его пределы.
✅Удобство использования: Использование flex-wrap упрощает разработку, так как автоматизирует перенос элементов и устраняет необходимость в сложных медиа-запросах.
flex-wrap — это свойство Flexbox, которое управляет переносом элементов на новую строку. Значение wrap позволяет элементам переноситься на следующую строку, если они не помещаются в одну.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых::before
2️⃣::after
3️⃣::first-line
4️⃣::first-letter
5️⃣::selection
Описание и примеры использования
1️⃣`::before` и `::after`:
Эти псевдоэлементы позволяют добавлять содержимое до и после содержимого выбранного элемента. Их часто используют для декоративных целей.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример ::before и ::after</title>
<style>
.button {
position: relative;
display: inline-block;
padding: 10px 20px;
background-color: #3498db;
color: #fff;
text-transform: uppercase;
text-decoration: none;
font-family: Arial, sans-serif;
}
.button::before, .button::after {
content: '';
position: absolute;
width: 100%;
height: 2px;
background-color: #fff;
transition: all 0.3s;
}
.button::before {
top: 0;
left: 0;
}
.button::after {
bottom: 0;
right: 0;
}
.button:hover::before {
width: 0;
}
.button:hover::after {
width: 0;
}
</style>
</head>
<body>
<a href="#" class="button">Кнопка</a>
</body>
</html>
В этом примере ::before и ::after используются для добавления анимационных линий к кнопке.
2️⃣`::first-line`:
Этот псевдоэлемент позволяет стилизовать первую строку текста внутри блока.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример ::first-line</title>
<style>
p::first-line {
font-weight: bold;
color: red;
}
</style>
</head>
<body>
<p>Это пример параграфа. Первая строка этого текста будет стилизована жирным шрифтом и красным цветом.</p>
</body>
</html>
3️⃣`::first-letter`:
Этот псевдоэлемент позволяет стилизовать первую букву блока текста.
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример ::first-letter</title>
<style>
p::first-letter {
font-size: 2em;
color: blue;
float: left;
margin-right: 5px;
}
</style>
</head>
<body>
<p>Это пример параграфа. Первая буква этого текста будет увеличена и окрашена в синий цвет.</p>
</body>
</html>
Почему это важно?
✅Стилизация без изменения HTML: Псевдоэлементы позволяют добавлять и стилизовать части содержимого без необходимости изменять HTML-разметку.
✅Декоративные эффекты: С их помощью можно создавать сложные визуальные эффекты и улучшать пользовательский интерфейс.
✅Удобство и гибкость: Псевдоэлементы облегчают реализацию многих задач, таких как добавление иконок, создания кастомных подчеркиваний и т.д.
Псевдоэлементы добавляют и стилизуют части содержимого элементов. Основные псевдоэлементы: ::before, ::after, ::first-line, ::first-letter и ::selection. Они позволяют улучшать дизайн и удобство интерфейсов без изменения HTML-кода.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовыхstyle="color: red;") имеют самую высокую специфичность.
✅B: Количество ID-селекторов в селекторе (например, #header).
✅C: Количество классов, атрибутов и псевдоклассов (например, .class, [type="text"], :hover).
✅D: Количество тегов и псевдоэлементов (например, div, h1, ::before).
Рассмотрим несколько примеров и определим их специфичность:
1️⃣#main-content — (0, 1, 0, 0)
2️⃣.article p — (0, 0, 1, 1)
3️⃣header h1 span — (0, 0, 0, 3)
4️⃣div#main .content .text — (0, 1, 2, 1)
Чем выше значения специфичности, тем выше приоритет стиля. Если два селектора имеют одинаковую специфичность, то стиль, который объявлен позже, будет применён.
Пример
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Пример специфичности</title>
<style>
p {
color: black; /* (0, 0, 0, 1) */
}
.text {
color: blue; /* (0, 0, 1, 0) */
}
#highlight {
color: red; /* (0, 1, 0, 0) */
}
p#highlight {
color: green; /* (0, 1, 0, 1) */
}
</style>
</head>
<body>
<p class="text" id="highlight">Этот текст будет зелёным.</p>
</body>
</html>
В этом примере на <p> элемент действует несколько селекторов с разной специфичностью:
1️⃣p имеет специфичность (0, 0, 0, 1)
2️⃣.text имеет специфичность (0, 0, 1, 0)
3️⃣#highlight имеет специфичность (0, 1, 0, 0)
4️⃣p#highlight имеет специфичность (0, 1, 0, 1)
Поскольку p#highlight имеет наивысшую специфичность (0, 1, 0, 1), он применяет стиль цвета зелёный.
Почему это важно?
✅Управление конфликтами стилей: Знание специфичности помогает правильно управлять стилями и избегать конфликтов.
✅Чтение и поддержка кода: Более специфичные селекторы позволяют писать CSS, который легко поддерживать и расширять.
✅Эффективность разработки: Понимание специфичности позволяет создавать более предсказуемый и стабильный код.
Специфичность селекторов определяет, какие CSS-стили будут применяться к элементу. Специфичность основывается на типах селекторов и их количестве. Чем более специфичный селектор, тем выше его приоритет.
👉 Можно посмотреть Примеры как отвечают люди на этот вопрос, или перейти К списку 1429 вопроса на Frontend разработчика. Ставь 👍 если нравится контент
🔐 База собесов | 🔐 База тестовых