Привет!
Давайте разберем принцип работы async/await под капотом. Посмотрим, как выполняется код с обычной и асинхронной функцией — это поможет понять, почему async/await ведет себя именно так, — и разберем, почему происходит неблокирующее ожидание.
Читать про async/await
@chulakov_dev
Давайте разберем принцип работы async/await под капотом. Посмотрим, как выполняется код с обычной и асинхронной функцией — это поможет понять, почему async/await ведет себя именно так, — и разберем, почему происходит неблокирующее ожидание.
Читать про async/await
@chulakov_dev
Привет!
Этой осенью будет много интересных IT-конференций. Рассказываем, в каких из них точно стоит поучаствовать, чтобы профессионально прокачаться, а также познакомиться с классными ребятами.
CrossConf
15.09 — Москва
Ежегодная конференция по кросс-платформенной разработке и трендам IT. После докладов желающие смогут продолжить общение с коллегами на afterparty.
Стачка
15–16.09 — Ульяновск
Десятая по счету международная IT-конференция. Темы выступлений охватят несколько разных направлений — от разработки до продаж.
FrontendConf
02–03.10 — Москва
Cамая масштабная конференция по frontend-разработке в России. Своим опытом поделятся ведущие разработчики из крупнейших IT-компаний.
Joker
09–10.10 — online
13–14.10 — Санкт-Петербург и online
Одна из старейших конференций для Java‑разработчиков. Здесь можно узнать практическую информацию об использовании Spring Boot и разобраться, как JVM работает «под капотом».
Heisenbug
10–11.10 — online
15–16.10 — Санкт-Петербург и online
Крупнейшая в России конференция по тестированию ПО. Ожидаются доклады для специалистов разных профилей: QA-инженеров, разработчиков, тимлидов, директоров по качеству и др.
Mobius
01–02.11 — online
09–10.11 — Санкт-Петербург и online
Конференция для специалистов, связанных с мобильной разработкой: iOS- и Android-разработчиков, архитекторов мобильных приложений, специалистов по DevOps и др.
HolyJS
02–03.11 — online
11–12.11 — Санкт-Петербург и online
Конференция для JavaScript‑разработчиков. JS‑разработку здесь рассматривают в разных ракурсах — от конкретных фреймворков до борьбы с техдолгом.
PiterPy
07.11 — online
13–14.11 — Санкт-Петербург и online
Конференция для тех, кто пишет на Python и использует его в работе.
HighLoad
27–28.11 — Москва
Конференция для разработчиков высоконагруженных систем. Мероприятие направлено на обмен знаниями о технологиях, позволяющих одновременно обслуживать тысячи и миллионы пользователей.
TeamLead Conf
30.11–01.12 — Москва
Профессиональная конференция только для тимлидов.
@chulakov_dev
Этой осенью будет много интересных IT-конференций. Рассказываем, в каких из них точно стоит поучаствовать, чтобы профессионально прокачаться, а также познакомиться с классными ребятами.
CrossConf
15.09 — Москва
Ежегодная конференция по кросс-платформенной разработке и трендам IT. После докладов желающие смогут продолжить общение с коллегами на afterparty.
Стачка
15–16.09 — Ульяновск
Десятая по счету международная IT-конференция. Темы выступлений охватят несколько разных направлений — от разработки до продаж.
FrontendConf
02–03.10 — Москва
Cамая масштабная конференция по frontend-разработке в России. Своим опытом поделятся ведущие разработчики из крупнейших IT-компаний.
Joker
09–10.10 — online
13–14.10 — Санкт-Петербург и online
Одна из старейших конференций для Java‑разработчиков. Здесь можно узнать практическую информацию об использовании Spring Boot и разобраться, как JVM работает «под капотом».
Heisenbug
10–11.10 — online
15–16.10 — Санкт-Петербург и online
Крупнейшая в России конференция по тестированию ПО. Ожидаются доклады для специалистов разных профилей: QA-инженеров, разработчиков, тимлидов, директоров по качеству и др.
Mobius
01–02.11 — online
09–10.11 — Санкт-Петербург и online
Конференция для специалистов, связанных с мобильной разработкой: iOS- и Android-разработчиков, архитекторов мобильных приложений, специалистов по DevOps и др.
HolyJS
02–03.11 — online
11–12.11 — Санкт-Петербург и online
Конференция для JavaScript‑разработчиков. JS‑разработку здесь рассматривают в разных ракурсах — от конкретных фреймворков до борьбы с техдолгом.
PiterPy
07.11 — online
13–14.11 — Санкт-Петербург и online
Конференция для тех, кто пишет на Python и использует его в работе.
HighLoad
27–28.11 — Москва
Конференция для разработчиков высоконагруженных систем. Мероприятие направлено на обмен знаниями о технологиях, позволяющих одновременно обслуживать тысячи и миллионы пользователей.
TeamLead Conf
30.11–01.12 — Москва
Профессиональная конференция только для тимлидов.
@chulakov_dev
Всем привет!
В работе с React каждый разработчик сталкивается с механизмом batching. Знаете ли вы, что это такое?
Batching — это техника объединения нескольких вызовов обновления состояния в одну операцию. Это помогает оптимизировать производительность, уменьшая количество перерисовок компонента.
Рассмотрим пример:
Почему так происходит? React группирует несколько изменений состояния, вызванных последовательно, в одно обновление, выполняя всего одну перерисовку.
Для приложений с частыми обновлениями состояния этот механизм становится настоящим спасением, обеспечивая плавность и отзывчивость интерфейса.
Но бывают ситуации, когда нам такое поведение не подходит. В этом случае React предоставляет метод с именем flushSync() в react-dom, который позволяет нам инициировать повторный рендеринг для определенного обновления состояния.
@chulakov_dev
В работе с React каждый разработчик сталкивается с механизмом batching. Знаете ли вы, что это такое?
Batching — это техника объединения нескольких вызовов обновления состояния в одну операцию. Это помогает оптимизировать производительность, уменьшая количество перерисовок компонента.
Рассмотрим пример:
export default function App() {Казалось бы, при нажатии на кнопку clear компонент должен перерисоваться дважды из-за двух изменений состояния. Но благодаря batching в логах вы увидите лишь одно сообщение: «Компонент был отрендерен!»
const [username, setUsername] = useState("JohnDoe"); const [followers, setFollowers] = useState(1000);
const handleClear = () => {
setFollowers(0); setUsername("");
}
useEffect(() => { console.log("Компонент был отрендерен!");
});
return ( /* JSX код */ );
}
Почему так происходит? React группирует несколько изменений состояния, вызванных последовательно, в одно обновление, выполняя всего одну перерисовку.
Для приложений с частыми обновлениями состояния этот механизм становится настоящим спасением, обеспечивая плавность и отзывчивость интерфейса.
Но бывают ситуации, когда нам такое поведение не подходит. В этом случае React предоставляет метод с именем flushSync() в react-dom, который позволяет нам инициировать повторный рендеринг для определенного обновления состояния.
const handleClick = () => {Но flushSync() стоит использовать осторожно, так как он может значительно снизить производительность.
flushSync(() => { setClicked(!clicked);
// react will create a re-render here });
setCount(count + 1);
// react will create a re-render here};
@chulakov_dev
Container-query — это долгожданная возможность в CSS, которая появилась в последних версиях браузеров. Она позволяет применять стили к элементам в зависимости от свойств их родительского контейнера. Это дает гораздо большую гибкость при создании адаптивных и резиновых layout.
Container-query работает аналогично медиа запросам, только вместо размеров viewport проверяются размеры родителя элемента.
Например, можно задать, что при ширине контейнера меньше 500 px текст внутри него будет отображаться в одну колонку вместо двух.
Это избавляет от лишних дополнительных оберток, упрощает структуру HTML и делает CSS-код более чистым и читабельным.
@chulakov_dev
Container-query работает аналогично медиа запросам, только вместо размеров viewport проверяются размеры родителя элемента.
Например, можно задать, что при ширине контейнера меньше 500 px текст внутри него будет отображаться в одну колонку вместо двух.
Это избавляет от лишних дополнительных оберток, упрощает структуру HTML и делает CSS-код более чистым и читабельным.
@chulakov_dev
Inline-функции — это механизм в Kotlin, который позволяет встраивать код функции непосредственно в вызывающий код вместо создания дополнительной функции на стеке вызовов. Это уменьшает накладные расходы на вызов функции высшего порядка и оптимизирует производительность.
Плюсы inline-функций
Уменьшение накладных расходов. Избегая создание дополнительных функций и стека вызовов, inline-функции уменьшают накладные расходы на выполнение кода.
Non-local return. Нелокальный return заключается в том, что он позволяет выйти из внешней функции, включая лямбды или анонимные функции, как если бы это была обычная инструкция return в самой функции.
Улучшение оптимизации. Компилятор может проводить более сложные оптимизации для встроенного кода, т.к. он полностью видит контекст вызова.
Представим, что у нас есть собственное расширение для Collection:
Чтобы избежать такой ситуации, в Kotlin мы можем использовать ключевое слово inline перед функцией высшего порядка. Это позволяет компилятору встроить код лямбда-выражения непосредственно в вызывающий код. Таким образом, мы избежим создания дополнительного объекта Function1 и вызова метода invoke, что повысит нашу производительность.
@chulakov_dev
Плюсы inline-функций
Уменьшение накладных расходов. Избегая создание дополнительных функций и стека вызовов, inline-функции уменьшают накладные расходы на выполнение кода.
Non-local return. Нелокальный return заключается в том, что он позволяет выйти из внешней функции, включая лямбды или анонимные функции, как если бы это была обычная инструкция return в самой функции.
Улучшение оптимизации. Компилятор может проводить более сложные оптимизации для встроенного кода, т.к. он полностью видит контекст вызова.
Представим, что у нас есть собственное расширение для Collection:
fun Collection.filter(predicate: (T) -> Boolean): Collection = //…При компиляции этого кода в Java создается объект специального типа и вызывается метод invoke для каждого элемента. Пример преобразования кода в Java будет выглядеть так:
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }
// Код на JavaВ результате каждого вызова функции высшего порядка с лямбда-выражением создается новый объект и выполняется вызов метода invoke. Если у нас есть большая коллекция или мы вызываем такую функцию много раз, это может значительно сказаться на производительности приложения.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = CollectionsKt.filter(numbers, new Function1() {
@Override
public Boolean invoke(Integer it) {
return it % 2 == 0;
}
});
Чтобы избежать такой ситуации, в Kotlin мы можем использовать ключевое слово inline перед функцией высшего порядка. Это позволяет компилятору встроить код лямбда-выражения непосредственно в вызывающий код. Таким образом, мы избежим создания дополнительного объекта Function1 и вызова метода invoke, что повысит нашу производительность.
@chulakov_dev
Всем привет!
Несколько лет назад в Android-приложениях для доставки функциональности пользователю применялся один цельный APK-файл, содержащий все компоненты приложения. С появлением Dynamic Delivery в 2018 году разработчики получили возможность собирать и доставлять части приложения в виде Dynamic Feature Modules (динамических модулей).
Сегодня расскажем, что такое Dynamic Features, какие возможности они предоставляют и как их можно использовать для улучшения гибкости и производительности в Android-приложениях.
Dynamic Features — это способ организации Android-приложения путем разделения его на небольшие модули, которые можно загружать и устанавливать на устройство пользователя по требованию.
Возможности Dynamic Features
➡️ Dynamic Features позволяют разделить приложение на модули, загружая только те, которые требуются, и таким образом значительно сократить размер установочного файла.
➡️ Вы можете выпускать обновления для отдельных модулей приложения, не требуя от пользователей загружать все приложение заново.
➡️ Разработчики могут работать над отдельными модулями независимо, что способствует быстрой разработке и более эффективному тестированию функциональности.
➡️ С Dynamic Features вы можете предоставить пользователям возможность загружать дополнительные функции по их выбору, делая приложение более персонализированным.
➡️ Если ваше приложение содержит контент, который часто обновляется, например новости, вы можете обновлять только модуль с контентом, минимизируя обновления для остальных частей приложения.
Dynamic Features дают разработчикам мощное средство для оптимизации размера приложения, улучшения гибкости и быстрого внедрения обновлений. Они позволяют создавать более персонализированные и производительные Android-приложения, предоставляя пользователям только ту функциональность, которая им действительно необходима.
@chulakov_dev
Несколько лет назад в Android-приложениях для доставки функциональности пользователю применялся один цельный APK-файл, содержащий все компоненты приложения. С появлением Dynamic Delivery в 2018 году разработчики получили возможность собирать и доставлять части приложения в виде Dynamic Feature Modules (динамических модулей).
Сегодня расскажем, что такое Dynamic Features, какие возможности они предоставляют и как их можно использовать для улучшения гибкости и производительности в Android-приложениях.
Dynamic Features — это способ организации Android-приложения путем разделения его на небольшие модули, которые можно загружать и устанавливать на устройство пользователя по требованию.
Возможности Dynamic Features
Dynamic Features дают разработчикам мощное средство для оптимизации размера приложения, улучшения гибкости и быстрого внедрения обновлений. Они позволяют создавать более персонализированные и производительные Android-приложения, предоставляя пользователям только ту функциональность, которая им действительно необходима.
@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
Привет, друзья!
На прошлой неделе у нас был пост про inline-функции. В продолжение темы расскажем о reified-типах в Kotlin.
Ключевое слово reified в Kotlin используется только в inline-функциях. Reified позволяет получить информацию о типе generic-параметра во время выполнения программы. В обычном случае информация о типах стирается и недоступна во время выполнения, но с помощью reified ее можно сохранять и использовать в других частях приложения.
Пример применения reified-типа с inline-функцией:
Информация о типе во время выполнения. Reified-типы позволяют получить информацию о типе параметра во время выполнения, что часто недоступно для обычных обобщенных функций.
Безопасность типов. Reified-типы предотвращают затирание типов данных во время выполнения, обеспечивая более высокую типовую безопасность.
Удобство использования. Применение reified-типов сокращает необходимость передачи информации о типе вручную, что делает код более чистым и читаемым.
Inline-функции и reified-типы предоставляют разработчикам мощные инструменты для оптимизации производительности, улучшения безопасности типов и структуры кода. Эти инструменты могут быть особенно полезными при работе с функциями, обеспечивая более эффективную и надежную разработку на языке Kotlin.
@chulakov_dev
На прошлой неделе у нас был пост про inline-функции. В продолжение темы расскажем о reified-типах в Kotlin.
Ключевое слово reified в Kotlin используется только в inline-функциях. Reified позволяет получить информацию о типе generic-параметра во время выполнения программы. В обычном случае информация о типах стирается и недоступна во время выполнения, но с помощью reified ее можно сохранять и использовать в других частях приложения.
Пример применения reified-типа с inline-функцией:
inline fun <reified T> printType() {Преимущества использования reified-типов с inline-функциями
println(T::class.simpleName)
}
fun main() {
printType<Int>() // Вывод: Int
printType<String>() // Вывод: String
}
Информация о типе во время выполнения. Reified-типы позволяют получить информацию о типе параметра во время выполнения, что часто недоступно для обычных обобщенных функций.
Безопасность типов. Reified-типы предотвращают затирание типов данных во время выполнения, обеспечивая более высокую типовую безопасность.
Удобство использования. Применение reified-типов сокращает необходимость передачи информации о типе вручную, что делает код более чистым и читаемым.
Inline-функции и reified-типы предоставляют разработчикам мощные инструменты для оптимизации производительности, улучшения безопасности типов и структуры кода. Эти инструменты могут быть особенно полезными при работе с функциями, обеспечивая более эффективную и надежную разработку на языке Kotlin.
@chulakov_dev
Друзья, привет!
В честь Дня знаний предлагаем решить задачку☝🏼
Пишите свои варианты в комментариях. Правильный ответ выложим там же.
@chulakov_dev
В честь Дня знаний предлагаем решить задачку☝🏼
Пишите свои варианты в комментариях. Правильный ответ выложим там же.
@chulakov_dev
Инвариантность, ковариантность и контравариантность являются концепциями, связанными с типами данных в контексте обобщений. Они определяют отношения между типами данных при использовании обобщений.
Инвариантность
Инвариантность означает, что тип является неизменным относительно других типов. В контексте обобщений, если у вас есть обобщенный тип например MyType<T>, MyType<A> и MyType<B> не считаются связанными друг с другом, даже если типы A и B связаны отношением наследования.
Ковариантность
Ковариантность позволяет использовать подтипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<out T>, то MyType<A> является подтипом MyType<B>, если A является подтипом B. Ковариантные типы могут использоваться только в «выходных» позициях.
Контравариантность
Контравариантность позволяет использовать супертипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<in T>, то MyType<A> является супертипом MyType<B>, если A является супертипом B. Контравариантные типы могут использоваться только во «входных» позициях.
Ковариантность и контравариантность полезны в обобщениях, так как позволяют создавать более гибкий и удобочитаемый код. Они обеспечивают безопасность типов и позволяют использовать обобщенные типы в различных контекстах, поддерживая отношения наследования и супертипов.
@chulakov_dev
Инвариантность
Инвариантность означает, что тип является неизменным относительно других типов. В контексте обобщений, если у вас есть обобщенный тип например MyType<T>, MyType<A> и MyType<B> не считаются связанными друг с другом, даже если типы A и B связаны отношением наследования.
Ковариантность
Ковариантность позволяет использовать подтипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<out T>, то MyType<A> является подтипом MyType<B>, если A является подтипом B. Ковариантные типы могут использоваться только в «выходных» позициях.
fun main() {В этом примере Producer<A> является подтипом Producer<B>, поэтому мы можем присвоить producerA (тип Producer<A>) переменной producerB (тип Producer<B>).
val producerA: Producer<A> = ProducerImplA()
val producerB: Producer<B> = producerA
}
interface Producer<out T> {
fun produce(): T
}
class A : B()
open class B
Контравариантность
Контравариантность позволяет использовать супертипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<in T>, то MyType<A> является супертипом MyType<B>, если A является супертипом B. Контравариантные типы могут использоваться только во «входных» позициях.
fun main() {В этом примере Consumer<B> является супертипом Consumer<A>, поэтому мы можем присвоить consumerB (тип Consumer<B>) переменной consumerA (тип Consumer<A>).
val consumerB: Consumer<B> = ConsumerImplB()
val consumerA: Consumer<A> = consumerB
}
interface Consumer<in T> {
fun consume(item: T)
}
open class B
class A : B()
Ковариантность и контравариантность полезны в обобщениях, так как позволяют создавать более гибкий и удобочитаемый код. Они обеспечивают безопасность типов и позволяют использовать обобщенные типы в различных контекстах, поддерживая отношения наследования и супертипов.
@chulakov_dev
Привет, друзья!
15-16 сентября в Ульяновске пройдет международная IT-конференция «Стачка», на которой выступит наш Frontend Team Lead Альберт Рыбалко с докладом «Таймеры в HTML5».
Спикер расскажет, что такое Host и почему он важен при работе с Web Api, подробно разберет работу таймеров и методы их очистки, а также объяснит, как микрозадачи выполняются в окружении JavaScript и какую роль они играют в асинхронном программировании.
Альберт выступит в секции «FrontEnd» 16 сентября.
@chulakov_dev
15-16 сентября в Ульяновске пройдет международная IT-конференция «Стачка», на которой выступит наш Frontend Team Lead Альберт Рыбалко с докладом «Таймеры в HTML5».
Спикер расскажет, что такое Host и почему он важен при работе с Web Api, подробно разберет работу таймеров и методы их очистки, а также объяснит, как микрозадачи выполняются в окружении JavaScript и какую роль они играют в асинхронном программировании.
Альберт выступит в секции «FrontEnd» 16 сентября.
@chulakov_dev
Всем привет!
Сегодня затронем важную тему — поверхностное и глубокое копирование в JavaScript.
Разберем, в чем разница между передачей данных по значению и по ссылке, рассмотрим разные способы копирования и расскажем, какие проблемы могут возникать при их осуществлении.
Читать пост
@chulakov_dev
Сегодня затронем важную тему — поверхностное и глубокое копирование в JavaScript.
Разберем, в чем разница между передачей данных по значению и по ссылке, рассмотрим разные способы копирования и расскажем, какие проблемы могут возникать при их осуществлении.
Читать пост
@chulakov_dev
Продолжаем серию заметок про запуск проекта с использованием Strapi. В первом посте мы рассказали, как собрать свой образ Strapi, а во втором — как запускать его в docker-окружении. Сегодня мы настроим подключение Strapi к базе данных Postgres.
👉🏻 Читать инструкцию
@chulakov_dev
👉🏻 Читать инструкцию
@chulakov_dev
Привет, друзья!
Предлагаем сегодня решить такую задачку. Нужно вывести в консоль числа от 0 до 10. Как вы думаете, будет ли код на картинке работать? Напишите в комментариях: да/нет и почему?
@chulakov_dev
Предлагаем сегодня решить такую задачку. Нужно вывести в консоль числа от 0 до 10. Как вы думаете, будет ли код на картинке работать? Напишите в комментариях: да/нет и почему?
@chulakov_dev
infer в примерах
Ключевое слово infer используется в контексте условных типов TypeScript для их автоматического вывода в определенных ситуациях и не может применяться вне расширения.
Эта конструкция языка позволяет нам определить переменную внутри нашего ограничения, на которую можно ссылаться или которую можно возвращать.
Другими словами, когда вы сталкиваетесь со сложными типами в TypeScript, infer помогает вытащить или определить неизвестные части этих типов, делая ваш код более гибким и легким для понимания.
Вы можете представить его как способ сказать TypeScript: «Выясни сам, какой здесь тип, и дай мне его использовать». Это особенно полезно, когда вы работаете с функциями или классами, где точные типы не всегда ясны из контекста.
Примеры применения ключевого слова infer.
1. Вывод типов из аргументов функции:
2. Примеры с рекурсивными типами.
Реализация типа Reverse:
Ключевое слово infer в TypeScript позволяет делать выводы о типах на основе переданных аргументов или примененных типов, что помогает улучшить гибкость и переиспользуемость кода.
@chulakov_dev
Ключевое слово infer используется в контексте условных типов TypeScript для их автоматического вывода в определенных ситуациях и не может применяться вне расширения.
Эта конструкция языка позволяет нам определить переменную внутри нашего ограничения, на которую можно ссылаться или которую можно возвращать.
Другими словами, когда вы сталкиваетесь со сложными типами в TypeScript, infer помогает вытащить или определить неизвестные части этих типов, делая ваш код более гибким и легким для понимания.
Вы можете представить его как способ сказать TypeScript: «Выясни сам, какой здесь тип, и дай мне его использовать». Это особенно полезно, когда вы работаете с функциями или классами, где точные типы не всегда ясны из контекста.
Примеры применения ключевого слова infer.
1. Вывод типов из аргументов функции:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function add(a: number, b: number): number {
return a + b;
}
type Result = ReturnType<typeof add>; // Result будет иметь тип number
2. Примеры с рекурсивными типами.
Реализация типа Reverse:
type actually = "123123123"
type Reverse<T extends string, R extends string = ""> = T extends `${infer Head}${infer Rest}`
? Reverse<`${Rest}`, `${Head}${R}`>
: R;
type result = Reverse<actually>; // "321321321"
Реализация типа Replace:
type actually = "912342181";
type Replace<T extends string, U extends string, R extends string = ""> = T extends ${infer Head}${infer Rest}
? Head extends U ? Replace<`${Rest}`, U, R> : Replace<`${Rest}`, U, `${R}${Head}`>
: R;
type result = Replace<actually, "1">; // "923428"
Ключевое слово infer в TypeScript позволяет делать выводы о типах на основе переданных аргументов или примененных типов, что помогает улучшить гибкость и переиспользуемость кода.
@chulakov_dev
CSS Logical Properties
CSS Logical Properties предоставляют альтернативу традиционным физическим свойствам, таким как
Они учитывают направление текста и другие языковые особенности.
CSS Logical Properties позволяют нам быть более гибкими в работе с мультиязычными интерфейсами и значительно сокращают количество кода, который нужно написать для адаптирования страниц под разные языки. Вот несколько примеров использования ⬇️
Логические отступы:
Логическая ширина и высота:
Логические границы:
Логические паддинги:
Применение логических свойств делает код более адаптивным к различным языкам и направлениям текста, облегчая создание универсальных стилей для разных локализаций.
@chulakov_dev
CSS Logical Properties предоставляют альтернативу традиционным физическим свойствам, таким как
width, height, margin, border, padding
и подобным, для более адаптивного оформления веб-страниц. Они учитывают направление текста и другие языковые особенности.
CSS Logical Properties позволяют нам быть более гибкими в работе с мультиязычными интерфейсами и значительно сокращают количество кода, который нужно написать для адаптирования страниц под разные языки. Вот несколько примеров использования ⬇️
Логические отступы:
.container {
margin-inline-start: 20px; /* Логический внутренний отступ слева (или справа) */
margin-block-end: 30px; /* Логический внутренний отступ вниз (в зависимости от направления текста) */
}
Логическая ширина и высота:
.elent {
inline-size: 200px; /* Логическая ширина */
block-size: 100px; /* Логическая высота */
}
Логические границы:
.box {
border-inline: 2px solid #333; /* Логическая граница в горизонтальном направлении */
border-block: 1px dashed #555; /* Логическая граница в вертикальном направлении */
}
Логические паддинги:
.content {
padding-inline: 15px; /* Логический внутренний отступ в горизонтальном направлении*/
padding-block: 10px; /* Логический внутренний отступ в вертикальном направлении */
}
Применение логических свойств делает код более адаптивным к различным языкам и направлениям текста, облегчая создание универсальных стилей для разных локализаций.
@chulakov_dev
Разбираемся в разнице: target="_blank" и target="blank" в HTML
🌐 Привет! Сегодня мы разберем интересный вопрос: в чем разница между
🎯 target="_blank"
Это стандартный способ открытия ссылки в новой вкладке браузера.
Каждый раз при клике на ссылку создается новая вкладка или новое окно браузера.
Пример использования:
🆚 target="blank"
При использовании target="blank" (без нижнего подчеркивания) браузер ведет себя по-другому.
"blank" здесь рассматривается как название фрейма, а не как ключевое слово. Если браузер не находит фрейм с таким именем, он создает новую вкладку с этим именем.
Повторные клики на разных ссылках с target="blank" будут перезаписывать содержимое одной и той же вкладки, вместо того чтобы открывать новую вкладку каждый раз.
Пример использования:
💡 Это знание особенно ценно, когда вы сталкиваетесь с ситуацией, в которой ссылка, предположительно с target="_blank", не открывается в новой вкладке или открывается только один раз.
Осознание того, что target="blank" без нижнего подчеркивания ведет к созданию одной постоянной вкладки для всех ссылок, может сэкономить вам много времени при отладке и поиске проблем в вашем коде.
@chulakov_dev
🌐 Привет! Сегодня мы разберем интересный вопрос: в чем разница между
target="_blank"
и target="blank"
при использовании в HTML? Детали могут показаться незначительными, но на практике они оказывают большое влияние на поведение ссылок в ваших веб-приложениях.🎯 target="_blank"
Это стандартный способ открытия ссылки в новой вкладке браузера.
Каждый раз при клике на ссылку создается новая вкладка или новое окно браузера.
Пример использования:
<a href="https://example.com" target="_blank">
Открыть example.com в новой вкладке
</a>
🆚 target="blank"
При использовании target="blank" (без нижнего подчеркивания) браузер ведет себя по-другому.
"blank" здесь рассматривается как название фрейма, а не как ключевое слово. Если браузер не находит фрейм с таким именем, он создает новую вкладку с этим именем.
Повторные клики на разных ссылках с target="blank" будут перезаписывать содержимое одной и той же вкладки, вместо того чтобы открывать новую вкладку каждый раз.
Пример использования:
<a href="https://example.com" target="blank">
Открыть example.com в именованном фрейме/вкладке "blank"
</a>
💡 Это знание особенно ценно, когда вы сталкиваетесь с ситуацией, в которой ссылка, предположительно с target="_blank", не открывается в новой вкладке или открывается только один раз.
Осознание того, что target="blank" без нижнего подчеркивания ведет к созданию одной постоянной вкладки для всех ссылок, может сэкономить вам много времени при отладке и поиске проблем в вашем коде.
@chulakov_dev
Изучаем Array.prototype.flat()
Сегодняшняя тема посвящена одной из полезных функций, введенной в ECMAScript 2019, — методу Array.prototype.flat().
📚 Что такое Array.prototype.flat()?
Метод flat() позволяет «выровнять» многомерные массивы ранее заданной глубине. Это особенно полезно, когда вы работаете с массивами, структура которых может быть сложной или неизвестной.
🌐 Как работает Array.prototype.flat()?
flat() принимает один необязательный аргумент — глубину, которая указывает, насколько глубоко метод должен «выравнивать» массив. По умолчанию глубина равна 1.
Пример использования:
@chulakov_dev
Сегодняшняя тема посвящена одной из полезных функций, введенной в ECMAScript 2019, — методу Array.prototype.flat().
📚 Что такое Array.prototype.flat()?
Метод flat() позволяет «выровнять» многомерные массивы ранее заданной глубине. Это особенно полезно, когда вы работаете с массивами, структура которых может быть сложной или неизвестной.
🌐 Как работает Array.prototype.flat()?
flat() принимает один необязательный аргумент — глубину, которая указывает, насколько глубоко метод должен «выравнивать» массив. По умолчанию глубина равна 1.
Пример использования:
let multiDimensionalArray = [1, [2, 3], [4, [5, 6]]];
// Выравниваем на один уровень
let flatArray = multiDimensionalArray.flat();
console.log(flatArray); // Выведет: [1, 2, 3, 4, [5, 6]]
// Выравниваем на два уровня
let flatArrayDeep = multiDimensionalArray.flat(2);
console.log(flatArrayDeep); // Выведет: [1, 2, 3, 4, 5, 6]
@chulakov_dev
Этапы рендеринга в браузере
Давайте вспомним, как это происходит 🤓
1. Загрузка ресурсов (Loading): браузер загружает HTML-документ и связанные ресурсы, такие как стили CSS, скрипты JavaScript, изображения и медиафайлы.
2. DOM: из полученного HTML-документа формируется Document Object Model (DOM).
3. CSSOM: параллельно с DOM браузер обрабатывает стили CSS и формирует CSS Object Model (CSSOM).
4. Accessibility Tree: параллельно с DOM и CSSOM формируется Accessibility Tree, которое содержит информацию о структуре веб-страницы и ее элементах для вспомогательных технологий.
5. Render Tree: на основе DOM и CSSOM формируется дерево рендеринга (Render Tree), содержащее только видимые элементы и их стили.
6. Scripting: выполнение JavaScript, который может изменять DOM и CSSOM, что приведет к повторным процессам рендеринга.
7. Layout: браузер вычисляет положение и размеры каждого элемента в Render Tree (Layout или Reflow).
8. Painting: отрисовка элементов на странице на основе информации из Render Tree.
9. Composite: разбиение отрисованных элементов на слои и их объединение для формирования окончательного изображения страницы.
10. Оптимизация производительности и кеширование: применение методов оптимизации и кеширование для улучшения производительности загрузки и рендеринга.
11. Обработка событий: взаимодействие пользователя с веб-страницей может вызывать обновления DOM и запускать новые циклы рендеринга.
Понимание этих процессов позволяет разработчикам более точно дебажить и устранять проблемы с производительностью и совместимостью, а также эффективно применять передовые техники веб-разработки.
@chulakov_dev
Давайте вспомним, как это происходит 🤓
1. Загрузка ресурсов (Loading): браузер загружает HTML-документ и связанные ресурсы, такие как стили CSS, скрипты JavaScript, изображения и медиафайлы.
2. DOM: из полученного HTML-документа формируется Document Object Model (DOM).
3. CSSOM: параллельно с DOM браузер обрабатывает стили CSS и формирует CSS Object Model (CSSOM).
4. Accessibility Tree: параллельно с DOM и CSSOM формируется Accessibility Tree, которое содержит информацию о структуре веб-страницы и ее элементах для вспомогательных технологий.
5. Render Tree: на основе DOM и CSSOM формируется дерево рендеринга (Render Tree), содержащее только видимые элементы и их стили.
6. Scripting: выполнение JavaScript, который может изменять DOM и CSSOM, что приведет к повторным процессам рендеринга.
7. Layout: браузер вычисляет положение и размеры каждого элемента в Render Tree (Layout или Reflow).
8. Painting: отрисовка элементов на странице на основе информации из Render Tree.
9. Composite: разбиение отрисованных элементов на слои и их объединение для формирования окончательного изображения страницы.
10. Оптимизация производительности и кеширование: применение методов оптимизации и кеширование для улучшения производительности загрузки и рендеринга.
11. Обработка событий: взаимодействие пользователя с веб-страницей может вызывать обновления DOM и запускать новые циклы рендеринга.
Понимание этих процессов позволяет разработчикам более точно дебажить и устранять проблемы с производительностью и совместимостью, а также эффективно применять передовые техники веб-разработки.
@chulakov_dev
Объединение интерфейсов в TypeScript
🔥 Сегодня рассмотрим одну замечательную возможность TypeScript — объединение интерфейсов, или merging interfaces. Этот механизм позволяет создавать более гибкие и масштабируемые типы.
🛠 Как работает объединение интерфейсов?
TypeScript уникален тем, что позволяет сливать несколько объявлений интерфейса в одно. Если вы объявляете два интерфейса с одинаковым именем, TypeScript автоматически объединит их.
Результирующий интерфейс User будет иметь свойства name, age и email
🔥 Сегодня рассмотрим одну замечательную возможность TypeScript — объединение интерфейсов, или merging interfaces. Этот механизм позволяет создавать более гибкие и масштабируемые типы.
🛠 Как работает объединение интерфейсов?
TypeScript уникален тем, что позволяет сливать несколько объявлений интерфейса в одно. Если вы объявляете два интерфейса с одинаковым именем, TypeScript автоматически объединит их.
interface User {
name: string;
age: number;
}
interface User {
email: string;
}
Результирующий интерфейс User будет иметь свойства name, age и email
const user: User = {
name: 'Алексей',
age: 30,
email: 'alexey@example.com',
}