Frontend | Вопросы собесов
Сайт: https://easyoffer.ru/ Все каналы: t.me/+xGeAw6ckJ4liYzQy Контакт для рекламы: @easyoffer_adv
Show more📈 Analytical overview of Telegram channel Frontend | Вопросы собесов
Channel Frontend | Вопросы собесов (@easy_javascript_ru) in the Russian language segment is an active participant. Currently, the community unites 17 871 subscribers, ranking 7 139 in the Technologies & Applications category and 36 827 in the Russia region.
📊 Audience metrics and dynamics
Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 17 871 subscribers.
According to the latest data from 28 August, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by -168 over the last 30 days and by -6 over the last 24 hours, overall reach remains high.
- Verification status: Not verified
- Engagement rate (ER): The average audience engagement rate is 6.72%. Within the first 24 hours after publication, content typically collects 4.47% reactions from the total number of subscribers.
- Post reach: On average, each post receives 1 201 views. Within the first day, a publication typically gains 799 views.
- Reactions and interaction: The audience actively supports content: the average number of reactions per post is 4.
- Thematic interests: Content is focused on key topics such as ставь, браузер, html, border, flex.
📝 Description and content policy
The author describes the resource as a platform for expressing subjective opinions:
“Сайт: https://easyoffer.ru/
Все каналы: t.me/+xGeAw6ckJ4liYzQy
Контакт для рекламы: @easyoffer_adv”
Thanks to the high frequency of updates (latest data received on 29 August, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.
<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;
}
Ставь 👍 и забирай 📚 Базу знаний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
Ставь 👍 и забирай 📚 Базу знанийGET, POST, PUT, DELETE)
GraphQL API (запросы только нужных данных)
WebSockets (реальное время, чаты, онлайн-игры)
GET https://api.example.com/users
Ответ от Backend
[
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
Ставь 👍 и забирай 📚 Базу знаний${}.
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
Ставь 👍 и забирай 📚 Базу знаний( 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; } /* Всегда будет красным */
Ставь 👍 и забирай 📚 Базу знаний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.
Ставь 👍 и забирай 📚 Базу знаний{} исторически использовались как ассоциативные массивы (ключ-значение), у 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" (никаких багов!)
Ставь 👍 и забирай 📚 Базу знаний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
Ставь 👍 и забирай 📚 Базу знаний