Chulakov Dev – Telegram
Chulakov Dev
1.16K subscribers
139 photos
5 videos
204 links
Канал команды разработки Студии Олега Чулакова.

Советы по Frontend- и Backend-разработке web-сервисов, мобильных приложений, статьи и презентации от наших разработчиков, анонсы проектов и многое другое.

Обсудить проект @YuraAndreev
Download Telegram
Мы создали в локальном репозитории ссылку на другой удаленный репозиторий (git remote add github-repo ...). Как сделать в него пуш, чтобы скопировать все содержимое репозитория (ветки, теги, коммиты и т.д.)?
Anonymous Quiz
4%
git push github-repo
18%
git push --clone github-repo
54%
git push -u origin github-repo
25%
git push --mirror github-repo
🔥13👍53
Привет, друзья!

Мы собрали ТОП-5 книг по JavaScript для тех, кто только собирается погрузиться в изучение этого языка.

📔 «Изучаем программирование на JavaScript», Э. Фримен, Э. Робсон

Считаем, что это лучшая книга для старта. Она научит вас основам JavaScript в легкой интерактивной форме. Авторы глубоко не погружаются в тему, но зато, прочитав ее, вы сможете начать писать свои первые элементарные скрипты.

📔 «Современный учебник JavaScript», И. Кантор

Самое популярное онлайн-издание по JavaScript в русском сегменте. В учебнике объясняется не только JS, но и то, как работает DOM, браузер, а также раскрываются другие важные темы. Идеальная вторая книга.

📔 «JavaScript: подробное руководство», Д. Флэнаган

Самая фундаментальная книга по JavaScript из когда-либо написанных. Осилив ее внушительный объем, можно в полной мере стать сенсеем.

📔 «Как устроен JavaScript», Д. Крокфорд

Небольшая, но емкая книга от создателя JSON. Автор понятно объясняет базовые вещи. При этом опытные senior-разработчики тоже найдут в ней что-то новое для себя.

📔 «Элегантный JavaScript», М. Хавербеке

Пожалуй, самая сложная, но и самая интересная книга по основам JavaScript. Внутри вы найдете задание по созданию своего языка программирования, которое обязательно стоит выполнить.

А вы читали эти книги? Поделитесь своей подборкой любимых изданий.

@chulakov_dev
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👌4🤩32
Привет!

Давайте разберем принцип работы async/await под капотом. Посмотрим, как выполняется код с обычной и асинхронной функцией — это поможет понять, почему async/await ведет себя именно так, — и разберем, почему происходит неблокирующее ожидание.

Читать про async/await

@chulakov_dev
🔥20👍31🤔1
Привет!

Этой осенью будет много интересных 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
👍155🔥1
Всем привет!

В работе с React каждый разработчик сталкивается с механизмом batching. Знаете ли вы, что это такое?

Batching — это техника объединения нескольких вызовов обновления состояния в одну операцию. Это помогает оптимизировать производительность, уменьшая количество перерисовок компонента.

Рассмотрим пример:

export default function App() { 
const [username, setUsername] = useState("JohnDoe"); const [followers, setFollowers] = useState(1000);
const handleClear = () => {
setFollowers(0); setUsername("");
}
useEffect(() => { console.log("Компонент был отрендерен!");
});
return ( /* JSX код */ );
}

Казалось бы, при нажатии на кнопку clear компонент должен перерисоваться дважды из-за двух изменений состояния. Но благодаря batching в логах вы увидите лишь одно сообщение: «Компонент был отрендерен!»

Почему так происходит? React группирует несколько изменений состояния, вызванных последовательно, в одно обновление, выполняя всего одну перерисовку.

Для приложений с частыми обновлениями состояния этот механизм становится настоящим спасением, обеспечивая плавность и отзывчивость интерфейса.

Но бывают ситуации, когда нам такое поведение не подходит. В этом случае React предоставляет метод с именем flushSync() в react-dom, который позволяет нам инициировать повторный рендеринг для определенного обновления состояния.

const handleClick = () => {
flushSync(() => { setClicked(!clicked);
// react will create a re-render here });
setCount(count + 1);
// react will create a re-render here};

Но flushSync() стоит использовать осторожно, так как он может значительно снизить производительность.

@chulakov_dev
🔥22👍61
Привет, друзья!

Предлагаем пошевелить мозгами и решить задачу на картинке.

Ниже выбирайте свой вариант ответа👇🏻
👍8
Что будет выведено в консоль?
Anonymous Quiz
40%
5
18%
10
17%
Синтаксическая ошибка
25%
undefined
Container-query — это долгожданная возможность в CSS, которая появилась в последних версиях браузеров. Она позволяет применять стили к элементам в зависимости от свойств их родительского контейнера. Это дает гораздо большую гибкость при создании адаптивных и резиновых layout.

Container-query работает аналогично медиа запросам, только вместо размеров viewport проверяются размеры родителя элемента.

Например, можно задать, что при ширине контейнера меньше 500 px текст внутри него будет отображаться в одну колонку вместо двух.

Это избавляет от лишних дополнительных оберток, упрощает структуру HTML и делает CSS-код более чистым и читабельным.

@chulakov_dev
👍22🔥82🤩2
Inline-функции — это механизм в Kotlin, который позволяет встраивать код функции непосредственно в вызывающий код вместо создания дополнительной функции на стеке вызовов. Это уменьшает накладные расходы на вызов функции высшего порядка и оптимизирует производительность.

Плюсы inline-функций

Уменьшение накладных расходов.
Избегая создание дополнительных функций и стека вызовов, inline-функции уменьшают накладные расходы на выполнение кода.

Non-local return. Нелокальный return заключается в том, что он позволяет выйти из внешней функции, включая лямбды или анонимные функции, как если бы это была обычная инструкция return в самой функции.

Улучшение оптимизации. Компилятор может проводить более сложные оптимизации для встроенного кода, т.к. он полностью видит контекст вызова.

Представим, что у нас есть собственное расширение для Collection:

fun  Collection.filter(predicate: (T) -> Boolean): Collection = //…
val numbers = listOf(1, 2, 3, 4, 5)
val evenNumbers = numbers.filter { it % 2 == 0 }

При компиляции этого кода в Java создается объект специального типа и вызывается метод invoke для каждого элемента. Пример преобразования кода в Java будет выглядеть так:

// Код на Java
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;
}
});

В результате каждого вызова функции высшего порядка с лямбда-выражением создается новый объект и выполняется вызов метода invoke. Если у нас есть большая коллекция или мы вызываем такую функцию много раз, это может значительно сказаться на производительности приложения.

Чтобы избежать такой ситуации, в Kotlin мы можем использовать ключевое слово inline перед функцией высшего порядка. Это позволяет компилятору встроить код лямбда-выражения непосредственно в вызывающий код. Таким образом, мы избежим создания дополнительного объекта Function1 и вызова метода invoke, что повысит нашу производительность.

@chulakov_dev
👍95🔥3
Всем привет!

Несколько лет назад в 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
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍2
Привет, друзья!

На прошлой неделе у нас был пост про inline-функции. В продолжение темы расскажем о reified-типах в Kotlin.

Ключевое слово reified в Kotlin используется только в inline-функциях. Reified позволяет получить информацию о типе generic-параметра во время выполнения программы. В обычном случае информация о типах стирается и недоступна во время выполнения, но с помощью reified ее можно сохранять и использовать в других частях приложения.

Пример применения reified-типа с inline-функцией:

inline fun <reified T> printType() {
println(T::class.simpleName)
}

fun main() {
printType<Int>() // Вывод: Int
printType<String>() // Вывод: String
}

Преимущества использования reified-типов с inline-функциями

Информация о типе во время выполнения.
Reified-типы позволяют получить информацию о типе параметра во время выполнения, что часто недоступно для обычных обобщенных функций.

Безопасность типов. Reified-типы предотвращают затирание типов данных во время выполнения, обеспечивая более высокую типовую безопасность.

Удобство использования. Применение reified-типов сокращает необходимость передачи информации о типе вручную, что делает код более чистым и читаемым.

Inline-функции и reified-типы предоставляют разработчикам мощные инструменты для оптимизации производительности, улучшения безопасности типов и структуры кода. Эти инструменты могут быть особенно полезными при работе с функциями, обеспечивая более эффективную и надежную разработку на языке Kotlin.

@chulakov_dev
🔥14👍4
Друзья, привет!

В честь Дня знаний предлагаем решить задачку☝🏼
Пишите свои варианты в комментариях. Правильный ответ выложим там же.

@chulakov_dev
🔥17👍1
Инвариантность, ковариантность и контравариантность являются концепциями, связанными с типами данных в контексте обобщений. Они определяют отношения между типами данных при использовании обобщений.

Инвариантность
Инвариантность означает, что тип является неизменным относительно других типов. В контексте обобщений, если у вас есть обобщенный тип например MyType<T>, MyType<A> и MyType<B> не считаются связанными друг с другом, даже если типы A и B связаны отношением наследования.

Ковариантность
Ковариантность позволяет использовать подтипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<out T>, то MyType<A> является подтипом MyType<B>, если A является подтипом B. Ковариантные типы могут использоваться только в «выходных» позициях.

fun main() {
val producerA: Producer<A> = ProducerImplA()
val producerB: Producer<B> = producerA
}
interface Producer<out T> {
fun produce(): T
}
class A : B()
open class B

В этом примере Producer<A> является подтипом Producer<B>, поэтому мы можем присвоить producerA (тип Producer<A>) переменной producerB (тип Producer<B>).

Контравариантность
Контравариантность позволяет использовать супертипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<in T>, то MyType<A> является супертипом MyType<B>, если A является супертипом B. Контравариантные типы могут использоваться только во «входных» позициях.

fun main() {
val consumerB: Consumer<B> = ConsumerImplB()
val consumerA: Consumer<A> = consumerB
}
interface Consumer<in T> {
fun consume(item: T)
}
open class B
class A : B()

В этом примере Consumer<B> является супертипом Consumer<A>, поэтому мы можем присвоить consumerB (тип Consumer<B>) переменной consumerA (тип Consumer<A>).

Ковариантность и контравариантность полезны в обобщениях, так как позволяют создавать более гибкий и удобочитаемый код. Они обеспечивают безопасность типов и позволяют использовать обобщенные типы в различных контекстах, поддерживая отношения наследования и супертипов.

@chulakov_dev
👍8🔥7
Привет, друзья!

15-16 сентября в Ульяновске пройдет международная IT-конференция «Стачка», на которой выступит наш Frontend Team Lead Альберт Рыбалко с докладом «Таймеры в HTML5».

Спикер расскажет, что такое Host и почему он важен при работе с Web Api, подробно разберет работу таймеров и методы их очистки, а также объяснит, как микрозадачи выполняются в окружении JavaScript и какую роль они играют в асинхронном программировании.

Альберт выступит в секции «FrontEnd» 16 сентября.

@chulakov_dev
25👍7🔥2
Всем привет!

Сегодня затронем важную тему — поверхностное и глубокое копирование в JavaScript.

Разберем, в чем разница между передачей данных по значению и по ссылке, рассмотрим разные способы копирования и расскажем, какие проблемы могут возникать при их осуществлении.

Читать пост

@chulakov_dev
👍18❤‍🔥1🔥1
Продолжаем серию заметок про запуск проекта с использованием Strapi. В первом посте мы рассказали, как собрать свой образ Strapi, а во втором — как запускать его в docker-окружении. Сегодня мы настроим подключение Strapi к базе данных Postgres.

👉🏻 Читать инструкцию

@chulakov_dev
👍12🔥6
Привет, друзья!

Предлагаем сегодня решить такую задачку. Нужно вывести в консоль числа от 0 до 10. Как вы думаете, будет ли код на картинке работать? Напишите в комментариях: да/нет и почему?

@chulakov_dev
🔥15👍5
infer в примерах

Ключевое слово 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
👍28🔥132👏1
CSS Logical Properties

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
21🔥8🤔2
Разбираемся в разнице: target="_blank" и target="blank" в HTML

🌐 Привет! Сегодня мы разберем интересный вопрос: в чем разница между 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
🔥27🤯5👍31😁1
Изучаем Array.prototype.flat()

Сегодняшняя тема посвящена одной из полезных функций, введенной в 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
21🔥9👍4