Channel: Frontend | Вопросы собесов
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥15
Проверить правильную иерархию HTML-заголовков важно для улучшения доступности (Accessibility) и SEO. Правильная структура заголовков помогает пользователям (включая тех, кто использует скринридеры) и поисковым системам лучше понимать содержание страницы.
Заголовки задают структуру страницы, разбивая контент на разделы и подразделы. Это как оглавление книги.
Люди, использующие вспомогательные технологии (например, скринридеры), полагаются на правильные заголовки для навигации по странице.
Поисковые системы оценивают структуру заголовков для индексации и понимания ключевых тем страницы.
Заголовок страницы (должен быть уникальным и только один на странице).
Подразделы
<h1>
.Подразделы
<h2>
, и так далее.<h1>Главный заголовок страницы</h1>
<h2>Раздел 1</h2>
<h3>Подраздел 1.1</h3>
<h3>Подраздел 1.2</h3>
<h2>Раздел 2</h2>
<h3>Подраздел 2.1</h3>
<h4>Подраздел 2.1.1</h4>
Вручную просмотрите HTML-код страницы и убедитесь, что заголовки идут в порядке. Например,
<h1>
→ <h2>
→ <h3>
и так далее, без "перескакивания". Избегайте "пропуска уровней" (например, от <h2>
сразу к <h4>
).В браузере откройте DevTools (например, в Chrome нажмите
F12
или Ctrl+Shift+I
). Перейдите на вкладку "Elements" (Элементы). Найдите заголовки (<h1>
, <h2>
и так далее) и проверьте их последовательность.Используйте расширения или инструменты для оценки доступности, такие как: Lighthouse (встроено в Chrome DevTools). Выполните аудит доступности и посмотрите рекомендации. WAVE (Web Accessibility Evaluation Tool) — онлайн-инструмент для анализа доступности. Эти инструменты покажут ошибки или пропуски в структуре заголовков.
Если вы работаете над большим проектом, можно написать скрипт для проверки иерархии заголовков.
const headings = [...document.querySelectorAll('h1, h2, h3, h4, h5, h6')];
headings.forEach((heading, index) => {
console.log(`${index + 1}: ${heading.tagName} - ${heading.textContent.trim()}`);
});
Для популярных CMS (например, WordPress) существуют плагины, которые проверяют структуру заголовков, например, Yoast SEO.
Ошибка: Пропуск уровней заголовков
<h1>Главный заголовок</h1>
<h3>Подраздел</h3> <!-- Пропущен <h2> -->
Исправление
<h1>Главный заголовок</h1>
<h2>Подраздел</h2>
Ошибка: Несколько
<h1>
на одной странице<h1>Главный заголовок</h1>
<h1>Еще один заголовок</h1>
Исправление
<h1>Главный заголовок</h1>
<h2>Еще один заголовок</h2>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20
Вызывает функцию с указанным контекстом this и массивом аргументов. Например: func.apply(context, [arg1, arg2]). Удобен для динамического вызова функций.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🔥9
Это два способа интеграции изменений из одной ветки в другую в системе контроля версий Git. Оба метода имеют свои особенности и подходят для разных сценариев.
Объединяет изменения из одной ветки в другую, создавая новый коммит слияния (merge commit). Этот метод сохраняет историю всех коммитов, включая все ветвления и слияния.
Предположим, у вас есть две ветки:
main
и feature
.В ветке
feature
вы сделали несколько коммитов.Вы хотите объединить изменения из
feature
в main
.git checkout main
git merge feature
Перемещает или переписывает базу текущей ветки на указанную базу другой ветки. Это переписывает историю коммитов, создавая новые коммиты для каждого из оригинальных коммитов.
Предположим, у вас есть две ветки:
main
и feature
.В ветке
feature
вы сделали несколько коммитов.Вы хотите перенести изменения из
feature
на текущий конец main
.git checkout feature
git rebase main
Merge: Сохраняет всю историю, включая коммиты слияния. История показывает, когда и как происходили слияния веток.
Rebase: Переписывает историю, делая её линейной. История показывает, как если бы все изменения были сделаны последовательно, без ветвлений.
Merge: Создает новый коммит слияния, который объединяет изменения из двух веток.
Rebase: Не создает коммит слияния. Перебазирование "переносит" коммиты одной ветки на другую.
Merge: Конфликты решаются один раз при слиянии.
Rebase: Конфликты могут возникнуть на каждом коммите, и их нужно решать поэтапно.
Merge: Хорош для сохранения полного контекста истории разработки, особенно в командной работе.
Rebase: Хорош для поддержания чистой, линейной истории, особенно перед слиянием ветки в основную ветку, например, main или master.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24
Это специальный синтаксис, позволяющий стилизовать определенные части элемента или добавлять специальные элементы (как бы "элементы-призраки"), не создавая для этого дополнительные теги в HTML. Псевдоэлементы предоставляют удобный способ внесения изменений в структуру документа, не затрагивая HTML.
Начинается с двойного двоеточия (
::
), за которым следует название псевдоэлемента. Например, ::before
или ::after
.::before
и ::after
: Позволяют вставлять содержимое до или после содержимого выбранного элемента соответственно. Очень часто используются для добавления декоративных элементов.p::before {
content: "«";
color: blue;
}
p::after {
content: "»";
color: blue;
}
::first-line
: Применяет стили к первой строке текста в блочном элементе.p::first-line {
font-weight: bold;
}
::first-letter
: Применяет стили к первой букве текста в блочном элементе.p::first-letter {
font-size: 200%;
}
::selection
: Применяет стили к части текста, которую пользователь выделил.p::selection {
background: yellow;
}
Работают как часть документа, но на самом деле не существуют в DOM-дереве, а создаются стилями.
Чтобы псевдоэлементы
::before
и ::after
отображались, необходимо задать свойство content
, даже если оно пустое (content: "";
).Могут быть стилизованы почти так же, как обычные элементы, но есть некоторые ограничения, например, связанные с взаимодействием с JavaScript.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24❤1
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍33🔥9
В современном веб-разработке существует несколько подходов к рендерингу веб-страниц, и помимо SSR (Server-Side Rendering), есть альтернативы, каждая из которых имеет свои особенности, преимущества и недостатки.
Вся логика рендеринга страницы осуществляется на стороне клиента (браузера) с помощью JavaScript. Сервер отправляет минимальный HTML (обычно пустой
<div>
с ID), а приложение загружается, рендерится и управляется на стороне клиента. Сервер отправляет статический HTML (например, через index.html
), а JavaScript (чаще всего — библиотека/фреймворк, например React, Vue или Angular) загружает необходимые данные и динамически создает интерфейс.<div id="app"></div>
<script src="bundle.js"></script>
Приложение становится очень интерактивным после инициализации.
Основная работа выполняется на клиентской стороне.
Легко добавлять сложные интерактивные компоненты.
Пользователь видит пустую страницу, пока загружается JavaScript и данные.
Поисковым системам сложнее индексировать страницы, так как контент рендерится только в браузере.
Больше ресурсов требуется на стороне клиента.
Сайт полностью генерируется на этапе сборки (build time) и сервер отдает готовые HTML-страницы. Это популярный подход в JAMstack-приложениях (JavaScript, APIs, Markup). HTML генерируется один раз (обычно через фреймворк вроде Next.js, Gatsby, Nuxt.js) во время сборки. Сайт раздается пользователям как готовый статический контент.
npm run build
HTML статичен и отдается сервером без обработки.
Поисковые системы могут легко индексировать готовый HTML.
Все вычисления выполняются заранее (во время сборки).
Для обновления нужно заново пересобирать сайт, что может занимать много времени.
Если страница сильно зависит от данных пользователя или часто меняется, SSG становится менее удобным.
Это гибрид между SSG и SSR. Вы создаете статический контент во время сборки, но некоторые страницы могут обновляться динамически при запросе, а сервер сохраняет их для следующих пользователей. Фреймворк (например, Next.js) генерирует страницы на этапе сборки, но для определенных страниц вы можете указать интервал обновления (
revalidate
). После этого сервер пересоберет страницу и кэширует ее.export async function getStaticProps() {
return {
props: {
data: fetchData(),
},
revalidate: 60, // Обновлять страницу каждые 60 секунд
};
}
Страницы отдаются как статические, но обновляются при необходимости.
Удобно для контента, который редко обновляется.
Поисковики видят статические страницы.
Нужно управлять кэшированием и интервалами обновления.
Если обновления контента слишком частые, ISR может не подойти.
Это подход, при котором разные версии страницы рендерятся для разных пользователей. Например, для пользователей с обычными браузерами вы используете CSR, а для поисковых ботов — SSR. Запросы от поисковых ботов обрабатываются сервером, который генерирует готовый HTML. Запросы от обычных пользователей обрабатываются через CSR. Этот подход используется с инструментами, такими как Prerender.io или встроенными решениями фреймворков.
Боты получают готовый HTML.
Пользователи получают интерактивные страницы через CSR.
Нужно отслеживать запросы и разделять их.
Генерация страницы на сервере может занять время.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16❤5🔥2
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32🔥3
Это ссылка, которая указывает путь к ресурсу относительно текущей страницы или корневого каталога веб-сайта, вместо указания полного пути (абсолютной ссылки).
Относительная ссылка
<a href="../contact.html">Контакты</a>
Абсолютная ссылка
<a href="https://example.com/contact.html">Контакты</a>
Указывают путь к ресурсу, который находится в текущем каталоге или подкаталоге.
<a href="page.html">Страница</a> <!-- Ресурс в текущем каталоге -->
Используются два символа точки (
..
) для перехода на уровень выше.<a href="../folder/page.html">Страница</a> <!-- Подъем на один уровень вверх -->
Указывают путь относительно корня веб-сайта, начиная с
/
.<a href="/images/photo.jpg">Фото</a> <!-- Начало пути от корня сайта -->
Относительные ссылки работают независимо от домена. Если вы разрабатываете сайт локально (например, через
localhost
), вам не нужно указывать абсолютный путь с доменом.Если домен или структура сайта меняется, относительные ссылки автоматически адаптируются, если структура каталогов остается прежней.
Меньше текста в коде, особенно если проект содержит множество ссылок.
Ссылка на файл в текущей папке
<a href="file.html">Файл в текущей папке</a>
Ссылка на файл в подкаталоге
<a href="subfolder/file.html">Файл в подкаталоге</a>
Ссылка на файл в родительской папке
<a href="../file.html">Файл в родительской папке</a>
Ссылка на файл относительно корня сайта
<a href="/folder/file.html">Файл в папке от корня</a>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21🔥2
Чтобы растянуть элемент на 100% (по ширине, высоте или обоим направлениям), нужно понимать контекст, от чего "100%" будет вычисляться. Значение
100%
в CSS основывается на родительском элементе. Рассмотрим различные случаи и подходы.Элемент займет всю ширину своего родителя.
<div style="width: 300px; background: lightblue;">
<div style="width: 100%; background: coral;">Я растянут по ширине!</div>
</div>
Элемент займет всю высоту родительского элемента.
<div style="height: 300px; background: lightblue;">
<div style="height: 100%; background: coral;">Я растянут по высоте!</div>
</div>
Для растяжения элемента как по ширине, так и по высоте относительно родителя используются
width: 100%;
и height: 100%;
.<div style="width: 300px; height: 300px; background: lightblue;">
<div style="width: 100%; height: 100%; background: coral;">Растянут по ширине и высоте!</div>
</div>
Если элемент нужно растянуть на весь экран, используются единицы
100vw
(ширина окна) и 100vh
(высота окна).<div style="width: 100vw; height: 100vh; background: coral;">
Я растянут на весь экран!
</div>
Для исключения полосы прокрутки можно использовать
width: calc(100vw - 16px); /* Учитывается ширина скролла */
Когда нужно растянуть элемент независимо от размера его содержимого, можно использовать
position: absolute
.<div style="position: relative; width: 300px; height: 300px; background: lightblue;">
<div style="position: absolute; top: 0; left: 0; right: 0; bottom: 0; background: coral;">
Я растянут абсолютно!
</div>
</div>
Flexbox автоматически растягивает вложенные элементы, если у них указаны свойства
flex: 1
или align-items: stretch
.<div style="display: flex; width: 300px; height: 300px; background: lightblue;">
<div style="flex: 1; background: coral;">Я растянут по Flexbox!</div>
</div>
CSS Grid также позволяет растягивать элементы.
<div style="display: grid; width: 300px; height: 300px; background: lightblue;">
<div style="width: 100%; height: 100%; background: coral;">Я растянут внутри Grid!</div>
</div>
Если нужно учесть отступы (padding) или границы (border), используйте свойство
box-sizing: border-box
. Это гарантирует, что элемент с width: 100%
и height: 100%
не будет "выходить за пределы" из-за отступов.<div style="width: 300px; height: 300px; background: lightblue;">
<div style="width: 100%; height: 100%; padding: 20px; box-sizing: border-box; background: coral;">
Я растянут с учетом отступов!
</div>
</div>
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25❤3
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28🔥3
Нет, Promise в JavaScript нельзя перезапустить. Промисы являются одноразовыми: после того как они переходят в одно из состояний — выполнен (resolved) или отклонён (rejected) — их состояние больше не может измениться. Это одно из ключевых свойств промисов.
Промис, как только выполняется, становится иммутабельным. После выполнения (
resolve
) или отклонения (reject
), он остаётся в этом состоянии навсегда.Промисы предназначены для представления единственного результата асинхронной операции. Их дизайн не предполагает повторного запуска той же самой асинхронной логики.
const myPromise = new Promise((resolve, reject) => {
resolve('Done!');
});
myPromise.then((result) => console.log(result)); // "Done!"
// Даже если вы попытаетесь вызвать resolve или reject снова, ничего не произойдет
myPromise.then((result) => console.log(result)); // "Done!" (результат уже закеширован)
Если вы хотите выполнить операцию заново, вместо "перезапуска" Promise нужно создать новый Promise или использовать функцию, которая возвращает новый Promise каждый раз.
function createPromise() {
return new Promise((resolve, reject) => {
setTimeout(() => resolve('Я новый промис!'), 1000);
});
}
// Первый вызов
createPromise().then((result) => console.log(result)); // "Я новый промис!"
// "Перезапуск"
createPromise().then((result) => console.log(result)); // "Я новый промис!" (новый промис создан)
Это синтаксический сахар над промисами. Если вам нужно "перезапустить" асинхронную операцию, просто вызовите асинхронную функцию ещё раз.
async function fetchData() {
return new Promise((resolve) => {
setTimeout(() => resolve('Данные загружены!'), 1000);
});
}
async function main() {
const data1 = await fetchData();
console.log(data1); // "Данные загружены!"
const data2 = await fetchData(); // "Перезапуск" fetchData
console.log(data2); // "Данные загружены!"
}
main();
Если вам нужно повторно попытаться выполнить операцию (например, в случае неудачи), можно реализовать "ретрай". Это особенно полезно для операций вроде сетевых запросов.
function fetchDataWithRetry(retries) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (Math.random() > 0.7) { // 70% шансов на ошибку
resolve('Данные успешно загружены!');
} else {
reject('Ошибка загрузки данных');
}
}, 1000);
}).catch((error) => {
if (retries > 0) {
console.log(`Повторная попытка... Осталось: ${retries}`);
return fetchDataWithRetry(retries - 1); // Рекурсивный вызов
} else {
throw error; // Если попытки исчерпаны, выбрасываем ошибку
}
});
}
fetchDataWithRetry(3)
.then((data) => console.log(data))
.catch((error) => console.error(error));
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤1
Это механизм в JavaScript, где объекты могут наследовать свойства и методы от других объектов.
1. Каждый объект имеет скрытую ссылку [[Prototype]], ведущую к его прототипу.
2. Используется для создания цепочек наследования без необходимости использования классов.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥7
В 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 недоступна
При использовании модулей (например,
import
и export
в ES6), все переменные и функции в модуле имеют собственную область видимости. Они не попадают в глобальную область видимости.export const myVar = 'Я переменная из модуля';
import { myVar } from './module1.js';
console.log(myVar); // "Я переменная из модуля"
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16
1. Улучшает SEO, так как контент доступен для поисковых систем сразу.
2. Ускоряет загрузку страниц, особенно для медленных устройств или сетей.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18🔥10❤3
В JavaScript, чтобы уничтожить объект
Web Worker
, необходимо использовать метод terminate()
. Этот метод останавливает выполнение worker'а, освобождает связанные с ним ресурсы и завершает его работу. После вызова terminate()
объект worker больше не может быть использован.Web Worker позволяет выполнять тяжелые операции в фоновом потоке, не блокируя основной поток (UI-поток). Однако, если worker больше не нужен, он продолжает существовать и занимает ресурсы (память, процессорное время). Чтобы избежать утечек памяти и оптимизировать работу приложения, важно уничтожать worker, когда он больше не используется.
Вы вызываете метод
terminate()
на экземпляре объекта worker. Это мгновенно останавливает выполнение фонового скрипта.// Создаем worker
const myWorker = new Worker('worker.js');
// Выполняем какие-то операции через worker
myWorker.postMessage('Hello, worker!');
// Завершаем работу worker, когда он больше не нужен
myWorker.terminate();
terminate()
worker полностью уничтожается и больше не может отправлять или получать сообщения.onmessage
), они автоматически удаляются.terminate()
не приведет к ошибке, но никакие операции через него больше работать не будут.const worker = new Worker('worker.js');
// Отправляем сообщение
worker.postMessage('Start working');
// Завершаем работу worker
worker.terminate();
// Попытка отправить сообщение после уничтожения worker
worker.postMessage('Will this work?'); // Ничего не произойдет, worker уже завершен
Если вы перезагружаете страницу или закрываете вкладку, все web worker автоматически уничтожаются браузером. Однако в рамках текущей сессии ответственность за уничтожение лежит на разработчике.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12
Это функция, которая выполняется сразу после определения.
1. Используется для создания изолированной области видимости, чтобы избежать конфликтов переменных.
2. Помогает инкапсулировать код и не загрязнять глобальную область.
Ставь 👍 если знал ответ, 🔥 если нет
Забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7👍6
Чтобы понять, что код работает корректно, нужно провести его тестирование, что включает в себя проверку кода на соответствие ожидаемым результатам в различных ситуациях. Вот основные подходы и шаги:
Прежде чем тестировать код, нужно понять, что он должен делать. Обычно для этого используют техническое задание или описание требований.
Например: если вы пишете функцию, которая складывает два числа, то ожидается, что при вызове
add(2, 3)
результат будет 5
.Тестирование предполагает выполнение кода с разными входными данными и проверку, что результат соответствует ожиданиям.
Вы запускаете код с различными значениями и проверяете результаты.
Пишете тестовые скрипты, которые автоматически проверяют корректность работы.
function add(a, b) {
return a + b;
}
Мы можем протестировать её так
console.log(add(2, 3)); // Должно вывести 5
console.log(add(0, 0)); // Должно вывести 0
console.log(add(-1, -1)); // Должно вывести -2
Однако лучше использовать автоматическое тестирование. Например, с помощью Jest
test('add function works correctly', () => {
expect(add(2, 3)).toBe(5);
expect(add(0, 0)).toBe(0);
expect(add(-1, -1)).toBe(-2);
});
Иногда код может работать корректно для обычных данных, но давать сбои в "необычных" случаях. Эти ситуации называют крайними случаями.
Пустой ввод (например,
add()
вместо двух чисел).Очень большие числа.
Неправильные типы данных (например, строка вместо числа).
console.log(add()); // undefined или ошибка
console.log(add('2', 3)); // Может вернуть '23' или ошибку, если функция не проверяет типы
Если код не работает как надо, нужно использовать инструменты для отладки
Вывод данных для проверки логики.
Для работы с JavaScript в реальном времени.
Позволяет пошагово выполнять код.
Иногда корректная работа кода связана не только с правильным результатом, но и с его скоростью. Если код работает слишком медленно, это может быть проблемой. Инструменты, такие как
performance.now()
в JavaScript, позволяют измерять время выполнения функций.После тестов полезно показать код другим разработчикам для проверки (code review) или провести тестирование с реальными пользователями. Это позволяет найти ошибки, которые могли быть упущены.
Ставь 👍 и забирай 📚 Базу знаний
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤3
HTML Embed Code: