Время: {this.state.time} секунд
;\n }\n}\n\nФункциональный компонент (хуки делают все проще) \nfunction Timer() {\n const [time, setTime] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => setTime(t => t + 1), 1000);\n return () => clearInterval(timer);\n }, []);\n\n returnВремя: {time} секунд
;\n}\n\n🟠Лучшая производительность (меньше потребления памяти) \nКлассовые компоненты используют экземпляры классов, а функциональные компоненты – просто функции. \nСоздают экземпляры this \nОбрабатывают setState \nХранят лишние связи и контексты \nНе создают this \nИспользуют только нужные данные \nОптимизируются через React.memo\nconst Button = React.memo(({ onClick }) => {\n console.log(\"Ререндер кнопки\");\n return ;\n});\n\nfunction App() {\n const [count, setCount] = useState(0);\n const increment = useCallback(() => setCount(c => c + 1), []);\n\n return (\nСчетчик: {count}
\n \nПривет, мир!
;\n}\n\n🟠Функциональные компоненты – будущее React \nReact официально рекомендует использовать функциональные компоненты \nDan Abramov (разработчик React) \nНовые фичи React (Suspense, Server Components) создаются для функциональных компонентов \nКлассы не работают в React Server Components \nБольшинство современных библиотек (Redux Toolkit, React Query) рассчитаны на хуки \n\nСтавь 👍 и забирай 📚 Базу знаний","datePublished":"2025-02-12T09:10:10Z","dateModified":"2025-02-12T09:10:10Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3712},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":12},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":25}]}},{"@type":"ListItem","position":10,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1112","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1112","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1112","headline":"Все новости из мира программирования на этом канале @umnyiprogrammist Подписывайтесь, чтобы не упустите ничег…","articleBody":"Все новости из мира программирования на этом канале @umnyiprogrammist\n\nПодписывайтесь, чтобы не упустите ничего важного\n\nСтавь 👍 и забирай 📚 Базу знаний","datePublished":"2025-02-12T07:00:24Z","dateModified":"2025-02-14T07:00:17Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2278},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":1},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":1}]}},{"@type":"ListItem","position":11,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1111","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1111","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1111","headline":"Профессиональная конференция по UX/UI 22 февраля в Москве пройдёт профильная UX/UI конференция для тех, кто п…","articleBody":"Профессиональная конференция по UX/UI\n\n22 февраля в Москве пройдёт профильная UX/UI конференция для тех, кто проектирует и создаёт интерфейсы. \n20+ экспертов топовых digital-агентств и RnD. 3 потока докладов. Кейсы от ведущих агентств. Активный нетворкинг. Афтепати в завершении дня. \nПрограмма и билеты на сайте. \n\nУзнать больше\n\n#реклама \nuxuiconf.ru\nО рекламодателе","datePublished":"2025-02-11T21:40:00Z","dateModified":"2025-02-13T19:40:05Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2421}]}},{"@type":"ListItem","position":12,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1110","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1110","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1110","headline":"🤔 Каким образом HTML превращается в страницу? 1. Загрузка: Браузер загружает HTML-документ. 2. Парсинг: HTML…","articleBody":"🤔 Каким образом HTML превращается в страницу?\n\n1. Загрузка: Браузер загружает HTML-документ.\n2. Парсинг: HTML разбивается на DOM (Document Object Model).\n3. Стилизация: CSS применяется к элементам DOM.\n4. Рендеринг: Браузер рендерит элементы на странице, создавая визуальное представление.\n\nСтавь 👍 если знал ответ, 🔥 если нет\nЗабирай 📚 Базу знаний","datePublished":"2025-02-11T16:10:50Z","dateModified":"2025-02-11T16:10:50Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3674},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":43},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":29}]}},{"@type":"ListItem","position":13,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1109","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1109","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1109","headline":"Когда подрядчик тележится, добавляйте его в Коллабу Битрикс24 Коллабы – платформа для эффективной работы с по…","articleBody":"Когда подрядчик тележится, добавляйте его в Коллабу\n\nБитрикс24 Коллабы – платформа для эффективной работы с подрядчиками. Тут обсуждения превращаются в задачи, а видео созвон можно собрать одной кнопкой. Любой проект можно разложить по полочкам с понятным ТЗ и обозначенными сроками. \n\nРаботайте в Битрикс24 и создавайте Коллабы с подрядчиками. \n\nНачать\n\n#реклама 16+\ncollabs.bitrix24.ru\nО рекламодателе","datePublished":"2025-02-11T13:11:36Z","dateModified":"2025-02-13T11:38:49Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2561}]}},{"@type":"ListItem","position":14,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1108","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1108","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1108","headline":"🤔 Какие преимущества у di? Dependency Injection (DI) – это паттерн проектирования, который помогает разделять…","articleBody":"🤔 Какие преимущества у di?\n\nDependency Injection (DI) – это паттерн проектирования, который помогает разделять зависимости и делает код гибче, тестируемее и поддерживаемее. Вместо того чтобы создавать зависимости внутри класса, они передаются (инъектируются) извне. \n\n🚩Почему DI полезен? \n\n🟠Уменьшает связность кода (Loose Coupling) \nВместо того чтобы жестко привязывать один модуль к другому, DI передает зависимости снаружи. \nclass UserService {\n constructor() {\n this.db = new Database(); // Прямо создаем зависимость\n }\n\n getUser(id) {\n return this.db.findUserById(id);\n }\n}\n\nС DI (гибкость) \nclass UserService {\n constructor(db) {\n this.db = db; // DI передает зависимость извне\n }\n\n getUser(id) {\n return this.db.findUserById(id);\n }\n}\n\n// Передаем нужную зависимость\nconst database = new Database();\nconst userService = new UserService(database);\n\n🟠Улучшает тестируемость (Unit-тесты проще) \nС DI можно подменять зависимости на заглушки (mock, fake, stub). \nconst userService = new UserService(); // Всегда использует реальную Database\nuserService.getUser(1); // Как протестировать без реальной БД? 🤔\n\nС DI (можно подменить зависимость) \nclass FakeDatabase {\n findUserById(id) {\n return { id, name: \"Тестовый пользователь\" };\n }\n}\n\nconst fakeDb = new FakeDatabase();\nconst userService = new UserService(fakeDb);\n\nconsole.log(userService.getUser(1)); // ✅ Тест без реальной БД\n\n🟠Улучшает расширяемость (легко менять зависимости) \nДопустим, сначала использовали MySQLDatabase, но решили перейти на MongoDatabase. \nclass UserService {\n constructor() {\n this.db = new MySQLDatabase(); // Нужно менять здесь\n }\n}\n\nС DI (добавляем новую зависимость без изменения кода UserService) \nconst db = new MongoDatabase(); // Просто передаем другую зависимость\nconst userService = new UserService(db);\n\n🟠Упрощает управление зависимостями (через DI-контейнеры) \nВ крупных приложениях удобно использовать DI-контейнер (например, InversifyJS для JavaScript/TypeScript). \nimport \"reflect-metadata\";\nimport { Container, injectable, inject } from \"inversify\";\n\n@injectable()\nclass Database {\n findUserById(id) {\n return { id, name: \"База данных\" };\n }\n}\n\n@injectable()\nclass UserService {\n constructor(@inject(Database) db) {\n this.db = db;\n }\n\n getUser(id) {\n return this.db.findUserById(id);\n }\n}\n\n// Настраиваем DI-контейнер\nconst container = new Container();\ncontainer.bind(Database).toSelf();\ncontainer.bind(UserService).toSelf();\n\n// Получаем объект с нужными зависимостями\nconst userService = container.get(UserService);\nconsole.log(userService.getUser(1));\n\nСтавь 👍 и забирай 📚 Базу знаний","datePublished":"2025-02-11T09:10:12Z","dateModified":"2025-02-11T09:10:12Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3770},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":18},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":36}]}},{"@type":"ListItem","position":15,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1107","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1107","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1107","headline":"Системный администратор Linux с нуля Бесплатный курс от Selectel Старт — 1 марта Освойте администрирование Li…","articleBody":"Системный администратор Linux с нуля\n\nБесплатный курс от Selectel\nСтарт — 1 марта\nОсвойте администрирование Linux на SelectOS.\n\nПосле курса вы сможете:\n- управлять инфраструктурой на базе Linux;\n- работать с командной строкой и основными утилитами;\n- управлять пользователями, файлами и правами доступа;\n- настраивать сети, SSH-соединения и мониторинг системы;\n- управлять пакетами и обновлениями программного обеспечения;\n- анализировать логи и устранять инциденты. \n\nСмотреть\n\n#реклама 16+\npromo.selectel.ru\nО рекламодателе","datePublished":"2025-02-11T04:11:43Z","dateModified":"2025-02-13T02:29:36Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2321},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":4}]}},{"@type":"ListItem","position":16,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1106","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1106","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1106","headline":"Ищу работу пол года Практически под каждым постом в этом канале я вижу комментарии от людей, которые ищут раб…","articleBody":"Ищу работу пол года\n\nПрактически под каждым постом в этом канале я вижу комментарии от людей, которые ищут работу по полгода. Это перерастает в обсуждение того, как нужно (или не нужно) искать работу, почему процесс найма сломан и как они откликались на фейковые вакансии.\n\nЧестно говоря, искать работу полгода — это нонсенс. Очевидно, что человек делает что-то не так. Главная ошибка, которую совершают многие, — это создание иллюзии поиска работы.\n\nТо есть человек вроде бы ищет работу, но делает это неэффективно, тратя время на нецелевые действия. Например:\n\n➖ Просматривает вакансии перед откликом.\n➖ Пытается понять, подходит ли он под вакансию. Если считает, что не подходит — не откликается.\n➖ Пишет сопроводительные письма (иногда даже уникальные под каждую вакансию).\n➖ Заполняет анкеты, проходит тесты.\n\nВсе эти действия отнимают время, но не приводят к результату.\n\nПочему это не работает?\n\nHR-менеджер не может вручную отсмотреть 2000 откликов, оценить каждое резюме и прочитать сопроводительные письма. Поэтому компании используют ATS-системы (системы автоматического подбора), которые анализируют резюме и определяют процент его соответствия вакансии.\n\nЧто делать, чтобы повысить шансы?\n\n1️⃣ Добавить ключевые навыки в резюме — и в основной текст, и в теги. Возьмите их с easyoffer.ru\n\n2️⃣ Убрать нерелевантный опыт, оставить только подходящий.\n\n3️⃣ Оформить опыт так, чтобы он выглядел релевантным. Если у вас его нет, укажите проекты, стажировки или другой опыт, который можно представить как работу от 1 года. Если опыт слишком большой, сузьте его до 6 лет.\n\n4️⃣ Откликаться на все вакансии без разбору. Если вы Junior, не ищите только стажер или Junior-вакансии — пробуйте везде. Не отказывайте себе сами, пусть это решит HR \n\n5️⃣ Сделать резюме публичным, потому что HR-менеджеры часто ищут кандидатов не только среди откликов, но и в базе резюме.\n\n6️⃣ Используйте ИИ по минимуму – ATS-системы считывают это и помечают \"сгенерировано ИИ\"\n\n‼️ Главное правило: чем больше откликов — тем выше шанс получить оффер. Делайте резюме удобным для ATS-систем, и вас заметят.\n\n1. Посмотрите видео о том как я вывел свою резюме в Топ1 на HH\n2. Посмотрите видео как я нашел первую работу\n3. Прочитайте этот кейс про оптимизацию резюме\n\nЕсли прям вообще тяжело.\n\nСоздайте несколько разных резюме. Создайте 2, 3 да хоть 10 резюме. Настройте авто-отлики и ждите приглашения на собесы.\n\nНе нужно создавать иллюзию поиска работы, сделайте несколько простых и актуальных действий.","datePublished":"2025-02-10T20:14:14Z","dateModified":"2025-02-10T20:14:14Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2976},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":29},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":97}],"sharedContent":{"@type":"SocialMediaPosting","datePublished":"2025-02-10T20:13:49Z"}}},{"@type":"ListItem","position":17,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1105","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1105","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1105","headline":"🤔 Как происходит взаимодействие с Git? 1. Инициализация репозитория: Создается локальный репозиторий с помощь…","articleBody":"🤔 Как происходит взаимодействие с Git?\n\n1. Инициализация репозитория: Создается локальный репозиторий с помощью git init или клонируется существующий через git clone.\n2. Изменение файлов: Вносятся изменения в файлы проекта.\n3. Отслеживание изменений: Добавляются изменения в индекс с помощью git add.\n4. Фиксация изменений: Изменения сохраняются в истории репозитория с помощью git commit.\n5. Синхронизация: Изменения передаются на удаленный сервер (git push) или загружаются (git pull).\n\nСтавь 👍 если знал ответ, 🔥 если нет\nЗабирай 📚 Базу знаний","datePublished":"2025-02-10T16:10:10Z","dateModified":"2025-02-10T16:10:10Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3813},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":20},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":24}]}},{"@type":"ListItem","position":18,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1104","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1104","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1104","headline":"🤔 Как css спрайты реализуются на странице или сайте? CSS-спрайты – это метод объединения нескольких изображен…","articleBody":"🤔 Как css спрайты реализуются на странице или сайте?\n\nCSS-спрайты – это метод объединения нескольких изображений в один файл для оптимизации загрузки и отображения на веб-странице. \n\n🚩Зачем нужны спрайты? \n\nУменьшают количество HTTP-запросов → вместо 10 изображений браузер загружает 1 файл \nУскоряют загрузку сайта → меньше сетевой нагрузки \nКэшируются в браузере → реже загружаются заново \n\n🟠Создание CSS-спрайта \nДопустим, у нас есть 3 иконки: \nicon-home.png \nicon-user.png \nicon-settings.png \nМы объединяем их в один файл (sprite.png): \n![sprite]\n\n🟠Использование спрайта с CSS \nТеперь нам нужно показать нужную часть изображения с помощью background-position. \n.sprite {\n background: url(\"sprite.png\") no-repeat;\n display: inline-block;\n width: 32px;\n height: 32px;\n}\n\n/* Позиции каждой иконки */\n.icon-home { background-position: 0 0; } /* Первая иконка */\n.icon-user { background-position: -32px 0; } /* Вторая иконка */\n.icon-settings { background-position: -64px 0; } /* Третья иконка */\n\nСтавь 👍 и забирай 📚 Базу знаний","datePublished":"2025-02-10T09:10:12Z","dateModified":"2025-02-10T09:10:12Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3962},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":17},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":25}]}},{"@type":"ListItem","position":19,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1103","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1103","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1103","headline":"⚡️ В сети начали массово сливать курсы и книги известных онлайн школ по айти Вот отсортированная база с тонно…","articleBody":"⚡️ В сети начали массово сливать курсы и книги известных онлайн школ по айти\n\nВот отсортированная база с тонной материала (постепенно пополняется):\n\nБАЗА (4687 видео/книг):\n\n(363 видео, 87 книги) — Python\n(415 видео, 68 книги) — Frontend\n(143 видео, 33 книги) — ИБ/Хакинг\n(352 видео, 89 книги) — С/С++\n(343 видео, 87 книги) — Java\n(176 видео, 32 книги) — Git\n(293 видео, 63 книги) — C#\n(174 видео, 91 книги) — DevOps\n(167 видео, 53 книги) — PHP\n(227 видео, 83 книги) — SQL/БД\n(163 видео, 29 книги) — Linux\n(114 видео, 77 книги) — Сисадмин\n(107 видео, 43 книги) — BA/SA\n(181 видео, 32 книги) — Go\n(167 видео, 43 книги) — Kotlin/Swift\n(112 видео, 24 книги) — Flutter\n(137 видео, 93 книги) — DS/ML\n(113 видео, 82 книги) — GameDev\n(183 видео, 37 книги) — Дизайн\n(129 видео, 73 книги) — QA\n(213 видео, 63 книги) — Rust\n(121 видео, 24 книги) — 1С\n(136 видео, 33 книги) — PM/HR\n\nСкачивать ничего не нужно — все выложено в Telegram","datePublished":"2025-02-10T07:00:21Z","dateModified":"2025-02-12T06:55:29Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2704},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":15},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":7}]}},{"@type":"ListItem","position":20,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1102","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1102","mainEntityOfPage":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru/posts/1102","headline":"🤔 Какие использовать препроцессоры? - Sass/SCSS: наиболее популярный и мощный для работы с CSS, поддерживает…","articleBody":"🤔 Какие использовать препроцессоры?\n\n- Sass/SCSS: наиболее популярный и мощный для работы с CSS, поддерживает переменные, вложенность и миксины.\n- Less: подходит для интеграции с JavaScript-проектами.\n- Stylus: гибкий и минималистичный синтаксис, удобен для небольших проектов.\n- Выбор зависит от требований проекта и команды.\n\nСтавь 👍 если знал ответ, 🔥 если нет\nЗабирай 📚 Базу знаний","datePublished":"2025-02-09T16:10:43Z","dateModified":"2025-02-09T16:10:43Z","author":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"publisher":{"@type":"Organization","name":"Frontend | Вопросы собесов","url":"https://telemetr.io/en/channels/1917151177-easy_javascript_ru","image":"https://img.telemetr.io/c/25KaBb/5431453649143450783?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":3989},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":21},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":12}]}}]}<button>) или ссылку (<a>) для взаимодействий? Хотя они внешне могут выглядеть одинаково, у них разные назначения и поведение.
🟠Когда использовать `<button>`?
Когда действие выполняется на странице без перехода на другую
Когда нужна интерактивность (отправка формы, открытие модального окна, запуск скрипта)
Отправка формы
Открытие/закрытие модального окна
Включение/выключение чего-то на странице
Взаимодействие с JavaScript (AJAX-запросы, события)
<button onclick="alert('Нажато!')">Кликни</button>
Пример кнопки в форме:
<form>
<input type="text" placeholder="Введите имя">
<button type="submit">Отправить</button>
</form>
🟠Когда использовать `<a>`?
Когда нужно перейти на другую страницу (или секцию сайта)
Когда ссылка ведет на внешний или внутренний ресурс
Навигация по сайту
Переход на другую страницу
Ссылки на соцсети, статьи, файлы
<a href="https://example.com">Перейти на сайт</a>
Ссылка внутри страницы (якорь)
<a href="#section">Перейти вниз</a>
<section id="section">Контент</section>
Открытие в новом окне
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
Открыть в новой вкладке
</a>
🟠Ошибки и неправильное использование
Ошибка: использовать <button> вместо ссылки
<button onclick="window.location.href='https://example.com'">Перейти</button>
Ставь 👍 и забирай 📚 Базу знанийinnerHTML – это свойство, которое позволяет вставлять HTML-код внутрь элемента как строку. Однако оно небезопасно и может привести к серьезным проблемам.
document.getElementById("content").innerHTML = "<h1>Привет!</h1>";
🟠Уязвимость: XSS-атаки (внедрение вредоносного кода)
Если innerHTML получает данные от пользователя (например, из формы или URL), хакер может вставить вредоносный JavaScript-код.
const userInput = "<script>alert('Вас взломали!');</script>";
document.getElementById("content").innerHTML = userInput;
🟠Проблемы с безопасностью CSP (Content Security Policy)
Если в веб-приложении включена CSP (защита от XSS), то innerHTML может нарушать политику безопасности.
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
🟠Случайное удаление обработчиков событий
Если заменить содержимое элемента через innerHTML, все обработчики событий внутри него удалятся.
document.getElementById("btn").addEventListener("click", () => {
alert("Нажато!");
});
document.getElementById("container").innerHTML = "<button id='btn'>Клик</button>";
document.getElementById("btn").click(); // Ошибка, обработчик удален
Ставь 👍 и забирай 📚 Базу знанийclass Counter extends React.Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
increment = () => {
this.setState({ count: this.state.count + 1 });
};
render() {
return (
<button onClick={this.increment}>
Счетчик: {this.state.count}
</button>
);
}
}
Функциональный компонент (хуки делают код проще)
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Счетчик: {count}
</button>
);
}
🟠Легче управлять жизненным циклом (useEffect vs componentDidMount)
В классах жизненный цикл* компонента состоит из нескольких методов (componentDidMount, componentDidUpdate, componentWillUnmount).
class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { time: 0 };
}
componentDidMount() {
this.timer = setInterval(() => {
this.setState({ time: this.state.time + 1 });
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
return <p>Время: {this.state.time} секунд</p>;
}
}
Функциональный компонент (хуки делают все проще)
function Timer() {
const [time, setTime] = useState(0);
useEffect(() => {
const timer = setInterval(() => setTime(t => t + 1), 1000);
return () => clearInterval(timer);
}, []);
return <p>Время: {time} секунд</p>;
}
🟠Лучшая производительность (меньше потребления памяти)
Классовые компоненты используют экземпляры классов, а функциональные компоненты – просто функции.
Создают экземпляры this
Обрабатывают setState
Хранят лишние связи и контексты
Не создают this
Используют только нужные данные
Оптимизируются через React.memo
const Button = React.memo(({ onClick }) => {
console.log("Ререндер кнопки");
return <button onClick={onClick}>Нажми</button>;
});
function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => setCount(c => c + 1), []);
return (
<div>
<p>Счетчик: {count}</p>
<Button onClick={increment} />
</div>
);
}
🟠Легче переиспользовать логику (React Hooks vs HOC/Render Props)
Раньше в классах код переиспользовали через HOC и Render Props, но это делало код сложным.
function withLogging(WrappedComponent) {
return class extends React.Component {
componentDidMount() {
console.log("Компонент монтирован");
}
render() {
return <WrappedComponent {...this.props} />;
}
};
}
Хуки (useEffect) делают код чище
function useLogger() {
useEffect(() => console.log("Компонент монтирован"), []);
}
function MyComponent() {
useLogger();
return <p>Привет, мир!</p>;
}
🟠Функциональные компоненты – будущее React
React официально рекомендует использовать функциональные компоненты
Dan Abramov (разработчик React)
Новые фичи React (Suspense, Server Components) создаются для функциональных компонентов
Классы не работают в React Server Components
Большинство современных библиотек (Redux Toolkit, React Query) рассчитаны на хуки
Ставь 👍 и забирай 📚 Базу знаний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));
Ставь 👍 и забирай 📚 Базу знанийicon-home.png
icon-user.png
icon-settings.png
Мы объединяем их в один файл (sprite.png):
![sprite]
🟠Использование спрайта с CSS
Теперь нам нужно показать нужную часть изображения с помощью background-position.
.sprite {
background: url("sprite.png") no-repeat;
display: inline-block;
width: 32px;
height: 32px;
}
/* Позиции каждой иконки */
.icon-home { background-position: 0 0; } /* Первая иконка */
.icon-user { background-position: -32px 0; } /* Вторая иконка */
.icon-settings { background-position: -64px 0; } /* Третья иконка */
Ставь 👍 и забирай 📚 Базу знаний