Ну, а ввечері перед сном ще запитаю про досвід.
У кожного свій шлях, але цікаво — на якому етапі ви зараз?
У кожного свій шлях, але цікаво — на якому етапі ви зараз?
Final Results
19%
🐣 Трейні / Курси
20%
🪴 Junior
33%
🔧 Middle
16%
🧭 Senior
8%
🦉 Tech / Team Lead
4%
👀 Я просто подивиться
Дивитись можна, чіпати не можна?
Часто виникає потреба “вимкнути” якийсь елемент, щоб він узагалі жодним чином не реагував на дії користувача: ні на кліки, ні на фокус. Зазвичай це або pointer-events: none, або event.preventDefault(), чи якісь інші трюки. А то й усе вкупі з tabindex="-1".
Однак в HTML уже давно існує спосіб надійно позбавити елемент будь-якої інтерактивности, а ба більше — викинути його з accessibility tree, “заховавши” від очей скринрідерів.
Це атрибут
Що в JS робиться ось так:
Якщо зробити елемент інертним, то весь його вміст стане повністю й остаточно неактивним для користувача, а також повністю зникне з радарів скринрідерів. І так, “розінертити” дочірні елементи не вийде — атрибут inert не має значення false, і інертність завжди наслідується.
inert входить до Baseline з 2023 року й підтримується всіма основними браузерами. Проте, у Safari (очікувано) є один нюанс: текст усередині inert-елемента все ще можна знайти при пошуку по сторінці (Cmd+F).
Чи можна його використовувати вже? Абсолютно так. За винятком цього невеликого бага, inert працює однаково й передбачувано в усіх браузерах, дозволяючи одним-єдиним атрибутом уникнути потреби городити купу костилів лише для того, щоб користувач не міг клікнути або табнутись у якийсь елемент.
Цим фактом особливо спішу з вами поділитись, бо сам дізнався про inert, обираючи тему для наступного допису.
А для вас це теж новина?
MDN
@babichdev
Часто виникає потреба “вимкнути” якийсь елемент, щоб він узагалі жодним чином не реагував на дії користувача: ні на кліки, ні на фокус. Зазвичай це або pointer-events: none, або event.preventDefault(), чи якісь інші трюки. А то й усе вкупі з tabindex="-1".
Однак в HTML уже давно існує спосіб надійно позбавити елемент будь-якої інтерактивности, а ба більше — викинути його з accessibility tree, “заховавши” від очей скринрідерів.
Це атрибут
inert, який відображає однойменну властивість DOM-елемента:<main id="my-content" inert>
<p>Щось неважливе</p>
</main>
Що в JS робиться ось так:
document.getElementById('my-content').inert = true;Якщо зробити елемент інертним, то весь його вміст стане повністю й остаточно неактивним для користувача, а також повністю зникне з радарів скринрідерів. І так, “розінертити” дочірні елементи не вийде — атрибут inert не має значення false, і інертність завжди наслідується.
І ви не будьте інертними — ставте вподобайки та поширюйте допис.
inert входить до Baseline з 2023 року й підтримується всіма основними браузерами. Проте, у Safari (очікувано) є один нюанс: текст усередині inert-елемента все ще можна знайти при пошуку по сторінці (Cmd+F).
Чи можна його використовувати вже? Абсолютно так. За винятком цього невеликого бага, inert працює однаково й передбачувано в усіх браузерах, дозволяючи одним-єдиним атрибутом уникнути потреби городити купу костилів лише для того, щоб користувач не міг клікнути або табнутись у якийсь елемент.
Цим фактом особливо спішу з вами поділитись, бо сам дізнався про inert, обираючи тему для наступного допису.
А для вас це теж новина?
MDN
@babichdev
🔥116❤20
Ну і останнє опитування з серії "Хто тут?!"
З чим ви працюєте, вчитеся працювати, чи просто цікавитеся?
(можна обрати кілька варіантів)
З чим ви працюєте, вчитеся працювати, чи просто цікавитеся?
(можна обрати кілька варіантів)
Final Results
42%
💻 Чистий, як сльоза, веб — HTML/CSS/JS
68%
⚛️ Невтопимий React / Next.js
14%
🌿 Вічнозелений Vue / Nuxt
15%
🔺 Суворий Angular / Nest
3%
⚡️ Витончені Svelte / Solid / Astro
22%
🧱 Тільки бекенд, тільки хардкор (NodeJS, Python)
4%
🤹 Екзотична екзотика (Rust, Go, WASM, може COBOL)
3%
👀 Не програмую, але цікавлюсь
На DOU Day за 500₴
Дарую квиток за донат на ЗСУ!
Друзі, цьогоріч я вперше виступаю на DOU Day 2025 — і дуже хочу, щоб хтось із вас був там теж. Це чудова нагода відвідати крутезний захід, і зустрітися особисто. Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 500 грн — ще один шанс виграти.
Ціль — 260 000 грн.
🔗 Банка:
https://send.monobank.ua/jar/4Pc6zfoth2
💳 Картка:
4441111124945795
Переможця оберу серед усіх донатерів у банці — в п'ятницю, 9 травня.
в коментарях є фото листа-прохання від військової частини
@babichdev
Дарую квиток за донат на ЗСУ!
Друзі, цьогоріч я вперше виступаю на DOU Day 2025 — і дуже хочу, щоб хтось із вас був там теж. Це чудова нагода відвідати крутезний захід, і зустрітися особисто. Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 500 грн — ще один шанс виграти.
Ціль — 260 000 грн.
🔗 Банка:
https://send.monobank.ua/jar/4Pc6zfoth2
💳 Картка:
4441111124945795
Переможця оберу серед усіх донатерів у банці — в п'ятницю, 9 травня.
в коментарях є фото листа-прохання від військової частини
@babichdev
🔥21
Нещодавно я розповідав про такий метод HTML-елемента, як closest, який шукає найближчий батьківський елемент, що відповідає заданому селектору. А сьогодні хочу поділитися з вами іншим методом, що нічого не шукає, але відповідає на питання — "А ось цей елемент точно справжній сантехнік той, що треба?"
І це —
Якщо повного співпадіння не буде, то й поверне він false:
На відміну від closest, matches перевіряє суто цільовий елемент і не шукає інших збігів. Звичайно, якщо обом методам дати однаковий і точний селектор — обидва спрацюють позитивно. Але якщо селектор “не точний”, closest цілком може повернути когось із батьків, а от matches скаже чітке “ні”.
Що цікаво, обидва методи працюють зі складними селекторами, включно з псевдокласами, тобто чудово справляться з отаким:
Але у випадку з тим же :not можуть бути нюанси. Коли я бавився з цим прикладом, то селектор вище чудово спрацьовував, а от ось такий:
уже чомусь ні, хоча в CSS цей селектор працює без проблем
Тож, якщо вам потрібно просто дізнатися, чи елемент відповідає селектору, і нічого більше, то ваш вибір — matches. Уявіть, що вам потрібно видалити елемент, тільки якщо він знаходиться в третьому за порядком section, але лише в тому випадку, якщо цей section має інші подібні елементи, а потрібний елемент — не останній.
Звичними нам методами це вимагало б купу переборів DOM і перевірок, а так — один кучерявий селектор і справу зроблено!
Підтримується абсолютно всіма актуальними бравзерами і є частиною Baseline.
🔗 MDN
⚡️ @babichdev
***
P.S. До речі, ви вже взяли участь в розіграші квитка на DOU Day усього за 500 гривень? Якщо ні — не зволікайте!
І це —
Element.matches, який просто перевіряє елемент, на якому він викликаний, на предмет відповідності селектору:<div class="container">
<div class="my-element"></div>
</div>
<noscript>
el.matches('.container .my-element'); // true
</noscript>
Якщо повного співпадіння не буде, то й поверне він false:
el.matches('.container'); // falseНа відміну від closest, matches перевіряє суто цільовий елемент і не шукає інших збігів. Звичайно, якщо обом методам дати однаковий і точний селектор — обидва спрацюють позитивно. Але якщо селектор “не точний”, closest цілком може повернути когось із батьків, а от matches скаже чітке “ні”.
Поки ми тут, не забудьте поставити вподобайку та поширити допис ;)
Що цікаво, обидва методи працюють зі складними селекторами, включно з псевдокласами, тобто чудово справляться з отаким:
:not(.container:first-child):hover .my-element
Але у випадку з тим же :not можуть бути нюанси. Коли я бавився з цим прикладом, то селектор вище чудово спрацьовував, а от ось такий:
.container:not(:first-child):hover .my-element
уже чомусь ні, хоча в CSS цей селектор працює без проблем
Тож, якщо вам потрібно просто дізнатися, чи елемент відповідає селектору, і нічого більше, то ваш вибір — matches. Уявіть, що вам потрібно видалити елемент, тільки якщо він знаходиться в третьому за порядком section, але лише в тому випадку, якщо цей section має інші подібні елементи, а потрібний елемент — не останній.
Звичними нам методами це вимагало б купу переборів DOM і перевірок, а так — один кучерявий селектор і справу зроблено!
Підтримується абсолютно всіма актуальними бравзерами і є частиною Baseline.
***
P.S. До речі, ви вже взяли участь в розіграші квитка на DOU Day усього за 500 гривень? Якщо ні — не зволікайте!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥44❤7👏4
Знаєте, коли я востаннє відчув невимовну радість від коду?
Вчора. І це було ніби вперше.
З роками, з досвідом, коли вже зробив, бачив, пробував стільки всього, починає здаватися, що тебе вже нічого не здивує. Ти тримав у руках jQuery 1.4 і верстав під IE6. Ти бачив стрімкий зліт і ганебну смерть AngularJS. Спостерігав на власні очі за народженням React — і досі чекаєш, коли згасне гайп навколо нього.
Але навіть після всього цього… досі по-дитячому щиру радість викликає одне просте:
ВОНО РОБЕ.
Коли ти припускаєш методом пальця до носа, що щось мало б спрацювати — і таки спрацьовує. Коли кілька днів копаєш баг, і в підсумку рішення — в один рядочок. А часом і в один символ. Коли складна задача раптом складається в елегантне рішення, яке ти колись давно бачив у статті — і забув.
І от ти записуєш цю думку кодом — і воно робе! Саме так, як уявляв: швидко, точно, надійно. І відчуваєш не просто задоволення. Відчуваєш — це зробив я!
Ці моменти — найцінніше для мене в щоденній роботі.
Так, наша робота давно вже ширша, ніж просто написання коду. І, будьмо чесні, кодинг — далеко не головна частина.
Але саме з цих маленьких митей відкриття й складається моє захоплення фахом.
***
P.S. Лишився лише один день до завершення розіграшу квитка на DOU Day 2025. Ви вже долучились?
P.P.S. А від чого ж я відчув таку невимовну радість учора? Якщо цей допис збере понад сотню реакцій і 500 переглядів — поділюся з вами завтра.
@babichdev
Вчора. І це було ніби вперше.
З роками, з досвідом, коли вже зробив, бачив, пробував стільки всього, починає здаватися, що тебе вже нічого не здивує. Ти тримав у руках jQuery 1.4 і верстав під IE6. Ти бачив стрімкий зліт і ганебну смерть AngularJS. Спостерігав на власні очі за народженням React — і досі чекаєш, коли згасне гайп навколо нього.
Але навіть після всього цього… досі по-дитячому щиру радість викликає одне просте:
ВОНО РОБЕ.
Коли ти припускаєш методом пальця до носа, що щось мало б спрацювати — і таки спрацьовує. Коли кілька днів копаєш баг, і в підсумку рішення — в один рядочок. А часом і в один символ. Коли складна задача раптом складається в елегантне рішення, яке ти колись давно бачив у статті — і забув.
І от ти записуєш цю думку кодом — і воно робе! Саме так, як уявляв: швидко, точно, надійно. І відчуваєш не просто задоволення. Відчуваєш — це зробив я!
Ці моменти — найцінніше для мене в щоденній роботі.
Так, наша робота давно вже ширша, ніж просто написання коду. І, будьмо чесні, кодинг — далеко не головна частина.
Але саме з цих маленьких митей відкриття й складається моє захоплення фахом.
***
P.S. Лишився лише один день до завершення розіграшу квитка на DOU Day 2025. Ви вже долучились?
P.P.S. А від чого ж я відчув таку невимовну радість учора? Якщо цей допис збере понад сотню реакцій і 500 переглядів — поділюся з вами завтра.
@babichdev
❤108🔥27
Що ж це за задача, рішення якої принесло мені днями стільки задоволення, що я аж цілий допис написав про це відчуття?
Ось вона — на ілюстрації до допису. Треба було зробити картку з динамічним лейаутом, де ширина першого елемента дорівнює найширшому з усіх, а висота самої картки — динамічна. Картки мають тягатися драг-н-дропом, при цьому використовуються наші внутрішні компоненти з дизайн-системи, які додають кілька обгорток, а сам вміст вставляється вже вглиб.
Очевидно, що таблиця не підійде (але я б її не взяв і так). Тому вибір очевидний — CSS Grid.
Отут постає кілька вимог, які дещо можуть завадити швидкій та наївній імплементації:
— ширина першої колонки — спільна, бо там номер картки;
— висота — довільна, однак grid за замовчуванням має однакові рядки;
І тут я згадав про subgrid:
Тут нюанс — якщо між головною сіткою і "наслідувачем" є обгортки, їм усім треба так само “прокинути” цю сітку:
І тоді сітка буде спільна для усіх елементів, незалежно, як вони між собою вкладені. Але лишається ще одне — динамічна висота картки. Тут мені трошки довелося подумати, але рішення виявилося настільки ж елегантним, як і простим:
Voila! — картки в сітці кожна має свою власну висоту!
І от коли все стало на свої місця, клацнуло як останні детальки LEGO, от тоді я й відчув ту мимолітну ейфорію, про яку писав.
Адже задоволення можна отримати не лише, якщо займатися тривалим, кхм, кодингом, а й тоді, коли вдається вирішити задачу в простий, проте елегантний спосіб, замість городити складне заради самої складности, рішення.
🔔 Тим часом розіграш квитка на DOU Day усього за 500 грн відбудеться уже сьогодні ввечері! Тож не зволікайте, аби не впустити таку нагоду!
@babichdev
.
Ось вона — на ілюстрації до допису. Треба було зробити картку з динамічним лейаутом, де ширина першого елемента дорівнює найширшому з усіх, а висота самої картки — динамічна. Картки мають тягатися драг-н-дропом, при цьому використовуються наші внутрішні компоненти з дизайн-системи, які додають кілька обгорток, а сам вміст вставляється вже вглиб.
Очевидно, що таблиця не підійде (але я б її не взяв і так). Тому вибір очевидний — CSS Grid.
Отут постає кілька вимог, які дещо можуть завадити швидкій та наївній імплементації:
— ширина першої колонки — спільна, бо там номер картки;
— висота — довільна, однак grid за замовчуванням має однакові рядки;
І тут я згадав про subgrid:
.container {
display: grid;
grid-template-columns: min-content 1fr;
}
.card {
display: grid;
grid-template-columns: subgrid;
}Тут нюанс — якщо між головною сіткою і "наслідувачем" є обгортки, їм усім треба так само “прокинути” цю сітку:
:where(.wrapper-1, .wrapper-2, …, .wrapper-n, .card) {
display: grid;
grid-template-columns: subgrid;
}І тоді сітка буде спільна для усіх елементів, незалежно, як вони між собою вкладені. Але лишається ще одне — динамічна висота картки. Тут мені трошки довелося подумати, але рішення виявилося настільки ж елегантним, як і простим:
.card {
height: max-content;
}Voila! — картки в сітці кожна має свою власну висоту!
І от коли все стало на свої місця, клацнуло як останні детальки LEGO, от тоді я й відчув ту мимолітну ейфорію, про яку писав.
Адже задоволення можна отримати не лише, якщо займатися тривалим, кхм, кодингом, а й тоді, коли вдається вирішити задачу в простий, проте елегантний спосіб, замість городити складне заради самої складности, рішення.
@babichdev
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥49❤8👏8
#цього_тижня
— Зазирнули по той бік ViewTransition у React і зʼясували, що це всього-на-всього обгортка над браузерним View Transition API.
— Познайомилися з атрибутом inert, який дозволяє зробити елемент видимим для ока, але невидимим для всього іншого.
— Розібрали, чим корисний метод Element.matches() і чим він відрізняється від Element.closest().
— Я поділився, які маленькі речі приносять мені справжнє задоволення в коді.
— А наступного дня показав, який саме код надихнув мене на попередній допис.
✨ А ще — разом з вами ми зібрали 25 642 грн на користь ЗСУ!
Який із дописів цього тижня сподобався вам найбільше? Напишіть у коментарях 👇
👍 @babichdev
.
— Зазирнули по той бік ViewTransition у React і зʼясували, що це всього-на-всього обгортка над браузерним View Transition API.
— Познайомилися з атрибутом inert, який дозволяє зробити елемент видимим для ока, але невидимим для всього іншого.
— Розібрали, чим корисний метод Element.matches() і чим він відрізняється від Element.closest().
— Я поділився, які маленькі речі приносять мені справжнє задоволення в коді.
— А наступного дня показав, який саме код надихнув мене на попередній допис.
✨ А ще — разом з вами ми зібрали 25 642 грн на користь ЗСУ!
Який із дописів цього тижня сподобався вам найбільше? Напишіть у коментарях 👇
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥26❤6👏4
Що приховують три крапки?
Вітаю, друзі! Сьогодні розповім вам про деякі неочевидні підводні камені так званого spread-оператора. Я сподіваюсь, ви вже в курсі, для чого він існує, тож перейду відразу до прихованих нюансів.
Порядок важливий
Коли ви "підмішуєте" обʼєкт, то значення будуть застосуватись в порядку додавання в новий обʼєкт:
Останнє входження ключа перезаписує попереднє. Spread — це не злиття, а послідовне копіювання полів з обʼєктів у новий.
undefined в масивах і обʼєктах
Ви спокійно можете розгорнути той же undefined або null в обʼєкт, а от з масивом такий трюк не пройде.
Усе через те, що масив вимагає, аби вхідний обʼєкт був Iterable, тобто такий, яким можна пройтися з Symbol.iterator, і nullish значення, очевидно такими не є. А от звичайний обʼєкт не такий вибагливий, і йому достатньо будь-якого значення, до якого можна застосувати Object.keys. У випадку з null та undefined цей метод просто поверне порожній список.
Object ⇄ Array? Ні.
Рівно з тієї самої причини ми можемо розмазати масив в обʼєкт, але не можемо зробити навпаки:
Spread у масиві очікує ітерабельність — тобто наявність Symbol.iterator. Обʼєкти цього не мають (за замовчуванням), тому розгортання летить з помилкою.
Натомість spread в обʼєкті потребує лише перелічуваних властивостей. А масив — це просто обʼєкт із числовими ключами, які чудово підходять під це визначення.
... не любить порожнечі
Spread-оператор не просто “копіює” масив — він перетворює його дірки на явно присутні undefined.
У масиві a на індексах 1, 2, 3 немає значень — це так звані дірки (sparse elements). Але при
... не копіює вміст обʼєкта
Технічно. Він поверхнево копіює перший рівень масива або обʼєкта. І якщо там примітивні значення, то можна сказати, це "копія". Але якщо є вкладеності, то
А ще
***
Якщо дізналися щось нове — напишіть у коментарях, що саме здивувало чи стало у пригоді.
А далі — обирати вам! Про що буде наступний допис?
🔥 — Дірки в масивах: як вони зʼявляються і що ламають
❤️ — Symbol.iterator: ітерабельність під капотом
🤔 — Чи настільки різні масиви та обʼєкти?
✅ @babichdev
.
Вітаю, друзі! Сьогодні розповім вам про деякі неочевидні підводні камені так званого spread-оператора. Я сподіваюсь, ви вже в курсі, для чого він існує, тож перейду відразу до прихованих нюансів.
Порядок важливий
Коли ви "підмішуєте" обʼєкт, то значення будуть застосуватись в порядку додавання в новий обʼєкт:
{ a: 1, b: 2, ...{ b: 3 } } // { a: 1, b: 3 }
{ ...{ b: 3 }, a: 1, b: 2 } // { a: 1, b: 2 }Останнє входження ключа перезаписує попереднє. Spread — це не злиття, а послідовне копіювання полів з обʼєктів у новий.
undefined в масивах і обʼєктах
Ви спокійно можете розгорнути той же undefined або null в обʼєкт, а от з масивом такий трюк не пройде.
{ ...undefined } // {}
[...undefined] // 💥 TypeErrorУсе через те, що масив вимагає, аби вхідний обʼєкт був Iterable, тобто такий, яким можна пройтися з Symbol.iterator, і nullish значення, очевидно такими не є. А от звичайний обʼєкт не такий вибагливий, і йому достатньо будь-якого значення, до якого можна застосувати Object.keys. У випадку з null та undefined цей метод просто поверне порожній список.
Object ⇄ Array? Ні.
Рівно з тієї самої причини ми можемо розмазати масив в обʼєкт, але не можемо зробити навпаки:
[...{ a: 1 }] // 💥 TypeError: object is not iterable
{ ...[1, 2] } // { 0: 1, 1: 2 }Spread у масиві очікує ітерабельність — тобто наявність Symbol.iterator. Обʼєкти цього не мають (за замовчуванням), тому розгортання летить з помилкою.
Натомість spread в обʼєкті потребує лише перелічуваних властивостей. А масив — це просто обʼєкт із числовими ключами, які чудово підходять під це визначення.
... не любить порожнечі
const a = [1, , , , 5]; // [1, empty × 3, 5]
const b = [...a]; // [1, undefined, undefined, undefined, 5]
console.log(1 in a); // false
console.log(1 in b); // true
Spread-оператор не просто “копіює” масив — він перетворює його дірки на явно присутні undefined.
У масиві a на індексах 1, 2, 3 немає значень — це так звані дірки (sparse elements). Але при
...a вони ущільнюються: JavaScript вставляє на їхнє місце undefined, і ці індекси стають реально присутніми в структурі масиву.... не копіює вміст обʼєкта
Технічно. Він поверхнево копіює перший рівень масива або обʼєкта. І якщо там примітивні значення, то можна сказати, це "копія". Але якщо є вкладеності, то
... скопіює посилання на них, а не зробить клоновані копії.const original = {
value: 1,
nested: { deep: true },
};
const copy = { ...original };
copy.nested.deep = false;
console.log(original.nested.deep); // falseА ще
... копіює виключно перший видимий рівень. Тобто прототип, неперелічувані властивості, символи — усе піде під ніж, і ви отримаєте стерильну копію.***
Якщо дізналися щось нове — напишіть у коментарях, що саме здивувало чи стало у пригоді.
А далі — обирати вам! Про що буде наступний допис?
🔥 — Дірки в масивах: як вони зʼявляються і що ламають
❤️ — Symbol.iterator: ітерабельність під капотом
🤔 — Чи настільки різні масиви та обʼєкти?
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥60❤43🤔23👏2
Порожнеча дивиться на тебе.
Масиви в JavaScript мають одну цікаву особливість — вони можуть бути "дірявими". Якщо дуже коротко — ми можемо явно присвоїти значення будь-якому індексу, і якщо цей індекс не є наступним після останнього значення, то утвориться розрив.
Дірка — не undefined! Хоча при звертанні до "дірки" вам і поверне undefined, насправді в самому масиві його не буде. Дірка означає повну відсутність значення за індексом, він просто не ініціалізований. Це випливає з того, що масив — це підвид обʼєкту, просто з певним інтерфейсом для впорядкування ключів.
По факту, масив з діркою, наприклад той самий
Індекс 1? Його просто немає.
Дірява поведінка
Дірки поводяться по своєму, і не завжди передбачувано. Візьмемо до прикладу масив
А тепер точнісінько такий масив, але замінимо дірку явним undefined:
Помітили різницю? Так от, map, forEach, filter, reduce, every, some просто ігнорують дірки, перестрибують їх. А for...of, for навпаки — зазирнуть у кожну дірочку.
А JSON.stringify взагалі перетворює дірки в масиві на… null.
До речі, як визначити, що це саме дірка, а не просто undefined? Перевірити наявність індекса в масиві. Якщо ключа немає, то це — дірка:
Дірка як палиця в колесі.
Така поведінка, очікувано, може призводити до багатьох дивних ситуацій, особливо при клонуванні чи порівнянні масивів. Ще більше збиватиму з пантелику той факт, що [].length віддає не фактичну кількість ключів, а "найбільший індекс + 1", що теж не додає впевнености при роботі з дірявими масивами.
Також JavaScript рушії не дуже полюбляють діряві масиви, бо робота з ними вимагає відмови від багатьох оптимізацій, які можна застосувати до безпереревних масивів. Я не буду вдаватися в деталі, лише зазначу, що це дійсно впливає і на споживання памʼяті, і на внутрішню швидкодію. Звичайно, ви не помітите різниці на масиві з десятком дірок, але якщо їх 100 000, 1 000 000, то втрати будуть відчутні.
Заштопати всі дірки!
Найочевидніша порада — не допускайте дірок. Якщо вам потрібна подібна структура, краще використати обʼєкт з власним ітератором. Якщо ж в руки потрапив такий масив, то його краще ущільнити: чи то зібрати лише реальні значення в інший масив, чи то заповнити дірки явним undefined — у будь-якому разі рушій вам подякує, а потім подякуєте і ви собі.
💬 А ви стикались із дірками в проді?
Чи, може, самі колись ненароком залишили? Поділіться досвідом у коментарях!
🔗 @babichdev
.
Масиви в JavaScript мають одну цікаву особливість — вони можуть бути "дірявими". Якщо дуже коротко — ми можемо явно присвоїти значення будь-якому індексу, і якщо цей індекс не є наступним після останнього значення, то утвориться розрив.
let arr = ['one', , 'three'];
// ['one', empty, 'three'];
arr[100] = 'value';
// ['one', empty, 'three', empty × 97, 'value']
Дірка — не undefined! Хоча при звертанні до "дірки" вам і поверне undefined, насправді в самому масиві його не буде. Дірка означає повну відсутність значення за індексом, він просто не ініціалізований. Це випливає з того, що масив — це підвид обʼєкту, просто з певним інтерфейсом для впорядкування ключів.
По факту, масив з діркою, наприклад той самий
['one', ,'three'], у обʼєктному записі виглядатиме так:{ 0: 'one', 2: 'three' }Індекс 1? Його просто немає.
Дірява поведінка
Дірки поводяться по своєму, і не завжди передбачувано. Візьмемо до прикладу масив
[1, , 3] та порахуємо квадрати його значень:[1, , 3].map(x => x * x) // [1, empty, 9]
А тепер точнісінько такий масив, але замінимо дірку явним undefined:
[1, undefined, 3].map(x => x * x) // [1, NaN, 9]
Помітили різницю? Так от, map, forEach, filter, reduce, every, some просто ігнорують дірки, перестрибують їх. А for...of, for навпаки — зазирнуть у кожну дірочку.
А JSON.stringify взагалі перетворює дірки в масиві на… null.
До речі, як визначити, що це саме дірка, а не просто undefined? Перевірити наявність індекса в масиві. Якщо ключа немає, то це — дірка:
const arr = ['one', , 'three'];
1 in arr; // false
Дірка як палиця в колесі.
Така поведінка, очікувано, може призводити до багатьох дивних ситуацій, особливо при клонуванні чи порівнянні масивів. Ще більше збиватиму з пантелику той факт, що [].length віддає не фактичну кількість ключів, а "найбільший індекс + 1", що теж не додає впевнености при роботі з дірявими масивами.
Також JavaScript рушії не дуже полюбляють діряві масиви, бо робота з ними вимагає відмови від багатьох оптимізацій, які можна застосувати до безпереревних масивів. Я не буду вдаватися в деталі, лише зазначу, що це дійсно впливає і на споживання памʼяті, і на внутрішню швидкодію. Звичайно, ви не помітите різниці на масиві з десятком дірок, але якщо їх 100 000, 1 000 000, то втрати будуть відчутні.
Заштопати всі дірки!
Найочевидніша порада — не допускайте дірок. Якщо вам потрібна подібна структура, краще використати обʼєкт з власним ітератором. Якщо ж в руки потрапив такий масив, то його краще ущільнити: чи то зібрати лише реальні значення в інший масив, чи то заповнити дірки явним undefined — у будь-якому разі рушій вам подякує, а потім подякуєте і ви собі.
💬 А ви стикались із дірками в проді?
Чи, може, самі колись ненароком залишили? Поділіться досвідом у коментарях!
І якщо було цікаво — не забудьте поширити допис або кинути лінк колезі.
.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥71❤18👏3🤔2
Виграти квиток на JavaScript fwdays'25 усього за сто гривень? Та легко!
Товариство, хто ще не придбав квиток на конференцію, але дуже хочe туди потрапити? Маєте шалену нагоду виграти один з двох Full Ticket квиточків та відвідати цю чудову подію і зустрітися з, до прикладу, Іллєю Климовим, чи Юрієм Артюхом. Ну і я десь там пробігатиму.
Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.
Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u
Номер картки банки
4441111125077309
Переможців оберу наступної середи, 20 травня, рандомом від monobank.
@babichdev
в коментарях є фото листа-прохання
Товариство, хто ще не придбав квиток на конференцію, але дуже хочe туди потрапити? Маєте шалену нагоду виграти один з двох Full Ticket квиточків та відвідати цю чудову подію і зустрітися з, до прикладу, Іллєю Климовим, чи Юрієм Артюхом. Ну і я десь там пробігатиму.
Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.
Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u
Номер картки банки
4441111125077309
Переможців оберу наступної середи, 20 травня, рандомом від monobank.
@babichdev
в коментарях є фото листа-прохання
🔥6❤4
Синьйор мусить знати все!
Ні. Не все.
Радше так: синьйор не має знати напамʼять увесь MDN. Як і мідл. Як і джун. Як і техлід. Взагалі, розробник не має знати всього напамʼять — це не показник експертности.
Розробка — це не контрольна робота. Це не про “знаєш або не знаєш”. Це про вміння орієнтуватися, коли стикаєшся з новим. Про вміння формулювати запит, знайти джерело, зрозуміти, перевірити, застосувати. Це — робота з невизначеністю.
Так, є база, без якої нікуди, і яка постійно змінюється. Є зони відповідальности. Є глибина, яку справедливо очікують від розробника певного рівня. Але навіть у синьйора в голові не вміщається весь Intl API, увесь Grid, або всі edge-кейси WebRTC. І це — нормально.
Найкращі розробники, з якими я працював — не ті, хто “все памʼятає”. А ті, хто не втрачає холодної голови, коли чогось не знає. Хто знає, як і де шукати. Хто не боїться питати. І хто не знецінює себе за пробіл — бо знає, що пробіл не означає порожнечу.
Коли я не знаю щось на співбесіді — це не провал. Це точка росту. Коли забуваю щось на етері — це не соромно. Це звичайний обсяг людської памʼяті, а не причина знецінювати себе.
Знання — це не інвентар, який мусить бути повним.
Це навичка працювати з невідомим.
Уміння рухатись уперед, навіть коли карти в голові ще не розкладені.
Між “я не знаю, як дізнатися” і “я не знаю, але розберусь” — ціла прірва. І справжній фахівець — це той, хто цю прірву давно перейшов.
Ти не мусиш усе знати.
Ти мусиш вміти дізнатися.
💬 А ви як ставитеся до моментів, коли чогось не знаєте?
Чи було таке відчуття, що «мусив же це знати!» — і що з ним робили?
P.S. На fwdays за 100 гривень?! Це можливо взагалі? Я кажу — так!
🔗 @babichdev
Ні. Не все.
Радше так: синьйор не має знати напамʼять увесь MDN. Як і мідл. Як і джун. Як і техлід. Взагалі, розробник не має знати всього напамʼять — це не показник експертности.
Розробка — це не контрольна робота. Це не про “знаєш або не знаєш”. Це про вміння орієнтуватися, коли стикаєшся з новим. Про вміння формулювати запит, знайти джерело, зрозуміти, перевірити, застосувати. Це — робота з невизначеністю.
Так, є база, без якої нікуди, і яка постійно змінюється. Є зони відповідальности. Є глибина, яку справедливо очікують від розробника певного рівня. Але навіть у синьйора в голові не вміщається весь Intl API, увесь Grid, або всі edge-кейси WebRTC. І це — нормально.
Найкращі розробники, з якими я працював — не ті, хто “все памʼятає”. А ті, хто не втрачає холодної голови, коли чогось не знає. Хто знає, як і де шукати. Хто не боїться питати. І хто не знецінює себе за пробіл — бо знає, що пробіл не означає порожнечу.
Коли я не знаю щось на співбесіді — це не провал. Це точка росту. Коли забуваю щось на етері — це не соромно. Це звичайний обсяг людської памʼяті, а не причина знецінювати себе.
Знання — це не інвентар, який мусить бути повним.
Це навичка працювати з невідомим.
Уміння рухатись уперед, навіть коли карти в голові ще не розкладені.
Між “я не знаю, як дізнатися” і “я не знаю, але розберусь” — ціла прірва. І справжній фахівець — це той, хто цю прірву давно перейшов.
Ти не мусиш усе знати.
Ти мусиш вміти дізнатися.
💬 А ви як ставитеся до моментів, коли чогось не знаєте?
Чи було таке відчуття, що «мусив же це знати!» — і що з ним робили?
P.S. На fwdays за 100 гривень?! Це можливо взагалі? Я кажу — так!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥112❤37👏6
Друзі, сьогодні я в гостях у Сергія Немчинського, і просто зараз розпочнеться стрим, на якому ми з ним обговоримо актуальні новини а ІТ. Про що конкретно — взагалі не здогадуюсь, але має бути цікаво )
https://www.youtube.com/live/3aBzFZjxb6w?si=dmx4xNBWdEdr1rA5
https://www.youtube.com/live/3aBzFZjxb6w?si=dmx4xNBWdEdr1rA5
YouTube
Основні ІТ-новини та тренди в Україні
🔗 Реєстрація на вебінар “Стратегія входу в ІТ у 2025: від нуля до розробника з першим комерційним досвідом”
https://go.foxminded.ua/459Uvaa
Ютуб канал Сергія Бабіча: https://www.youtube.com/@UCLRWnQw_G3kegbb4z-aRKSQ
Телеграм канал Сергія Бабіча: https:…
https://go.foxminded.ua/459Uvaa
Ютуб канал Сергія Бабіча: https://www.youtube.com/@UCLRWnQw_G3kegbb4z-aRKSQ
Телеграм канал Сергія Бабіча: https:…
🔥23❤12
Навіщо ходити на конференції та мітапи?
Хтось скаже — там обовʼязково треба слухати доповіді й набиратись нових знань. Хтось — що доповіді не важливі, а треба виключно нетворкатись. Хтось узагалі мовчки лутає мерч зі стендів партнерів.
А я вам скажу — на конференціях треба займатись усім! Якщо вас не дуже приваблює тема доповіді — сміливо йдіть пити каву та знайомитись. Втомились від розмов — ласкаво просимо до зали, там якраз виступає Бабіч. І не забудьте пробігтись партнерськими “будками” — там, окрім стікерів, шкарпеток та іншого дрібʼязку, іноді розігрують класні подарунки в обмін на ваші повні контакти, включно зі скрином з Дії. Але без жартів: саме на стендах я познайомився з багатьма HR, PR та рекрутерами, з якими досі спілкуємось. Одне таке знайомство навіть принесло мені роботу.
Спікер не образиться, якщо ви не прийдете на його доповідь (хіба скажете йому це в очі). Ба більше, я й сам відвідую від сили третину виступів своїх колег (включно зі своїм, свій ще жодного разу не пропускав). А решту часу — спілкуюсь, тусуюсь, обношу будки, з радістю фоткаюсь з учасниками.
До речі, ніколи не соромтесь зловити спікера й поставити питання (ну хіба він стрімко мчить до вбиральні й уже по виду ясно, що тисне на очі). Ми для того й виступаємо — щоб зацікавити. Якщо щось незрозуміло, або маєш свою точку зору — навіть протилежну — спікер з радістю приділить тобі хвильку.
Просто ми всі — енергетичні вампіри. Харчуємось вашими позитивними емоціями, а конференції для нас — це гастрономічні фестивалі.
Жартую (чи ні). Беріть від таких подій максимум: дізнавайтесь нове, знайомтесь, тусіть — і, по можливості, завжди потрапляйте на неофіційні пре- та афтепаті (але носіть із собою бетаргін).
Хто з вас був на моїй доповіді на DOU Day? Діліться відгуками в коментарях!
@babichdev
***
До речі, вже цієї суботи я виступатиму на JavaScript fwdays’25, і у вас є шанс виграти один із двох квитків на цю подію. Що треба зробити? Задонатити від 100 гривень та покластися на удачу!
Хтось скаже — там обовʼязково треба слухати доповіді й набиратись нових знань. Хтось — що доповіді не важливі, а треба виключно нетворкатись. Хтось узагалі мовчки лутає мерч зі стендів партнерів.
А я вам скажу — на конференціях треба займатись усім! Якщо вас не дуже приваблює тема доповіді — сміливо йдіть пити каву та знайомитись. Втомились від розмов — ласкаво просимо до зали, там якраз виступає Бабіч. І не забудьте пробігтись партнерськими “будками” — там, окрім стікерів, шкарпеток та іншого дрібʼязку, іноді розігрують класні подарунки в обмін на ваші повні контакти, включно зі скрином з Дії. Але без жартів: саме на стендах я познайомився з багатьма HR, PR та рекрутерами, з якими досі спілкуємось. Одне таке знайомство навіть принесло мені роботу.
Спікер не образиться, якщо ви не прийдете на його доповідь (хіба скажете йому це в очі). Ба більше, я й сам відвідую від сили третину виступів своїх колег (включно зі своїм, свій ще жодного разу не пропускав). А решту часу — спілкуюсь, тусуюсь, обношу будки, з радістю фоткаюсь з учасниками.
До речі, ніколи не соромтесь зловити спікера й поставити питання (ну хіба він стрімко мчить до вбиральні й уже по виду ясно, що тисне на очі). Ми для того й виступаємо — щоб зацікавити. Якщо щось незрозуміло, або маєш свою точку зору — навіть протилежну — спікер з радістю приділить тобі хвильку.
Жартую (чи ні). Беріть від таких подій максимум: дізнавайтесь нове, знайомтесь, тусіть — і, по можливості, завжди потрапляйте на неофіційні пре- та афтепаті (але носіть із собою бетаргін).
Хто з вас був на моїй доповіді на DOU Day? Діліться відгуками в коментарях!
@babichdev
***
До речі, вже цієї суботи я виступатиму на JavaScript fwdays’25, і у вас є шанс виграти один із двох квитків на цю подію. Що треба зробити? Задонатити від 100 гривень та покластися на удачу!
❤51🔥21👏4
Чи готові ви читати серії пов'язаних постів протягом, наприклад, кількох тижнів, замість різних "випадкових" фактів, чи вам краще таке прочитати за один раз у вигляді великої статті?
(хочу розповісти про Goog Enough Code, тему мого иступу на DOU Day)
(хочу розповісти про Goog Enough Code, тему мого иступу на DOU Day)
Anonymous Poll
80%
Так
13%
Так, якщо пости не поспіль
7%
Ні
❤8
Good Enough Code. ч.1
Код на відчепись, чи відчепіться від мого коду?
У кожного був цей момент: задачу закрито, ревʼю пройдено, усе працює — але щось свербить. Може, ще трохи підчистити? Перейменувати функцію? Винести шматок у модуль? Просто, щоб було "красивіше".
Так ось це і є зіткнення перфекціонізму з "достатністю" — і саме тут починається наша розмова про Good Enough Code.
Good Enough Code — це не "аби працювало". Це не код "на відчепись". Це підхід, у якому рішення достатньо хороше, щоб працювати, не створювати надмірний технічний борг і не витрачати зайві дні на причесування уже робочого коду. Це про точку, за якою зусилля на покращення вже не виправдані вигодою.
У реальності більшість задач — це не архітектурні шедеври, а практичні компроміси. І намагання зробити "ідеально" часто шкодить більше, ніж допомагає. Час іде на дрібниці, фідбек затримується, команда буксує в ревʼю. Продукт стоїть. Користувач чекає.
Парадоксально, але заради якості ми нерідко жертвуємо користю. І саме підхід GEC повертає фокус туди, де він має бути — на цінність.
Хороший код — це той, що вирішує задачу по суті, читається та підтримується без пояснювальної бригади, не ламається при зміні й дозволяє рухатися далі. Не ідеальний, а достатньо хороший, щоб не зупиняти розробку.
В той же час це не виправдання ліні. Це усвідомлений вибір, коли ти розумієш, де точка diminishing returns, що вигідніше бізнесу, і куди справді варто спрямувати свою енергію.
Бо в щоденній розробці виграє не той, хто пише красиво. А той, хто доставляє результат — і вміє вчасно зупинитись.
І якщо цей допис набере понад 150 реакцій та 1000 переглядів, то у наступних дописах ми з вами обовʼязково розглянемо:
– Як відрізнити достатній код від халтури?
– Які критерії “good enough”?
– Чому перфекціонізм — це теж технічний борг?
– Як впровадити цей підхід у команду й не перетворити все на безконтрольну лінь?
#good_enough_code #мислення_розробника
100 гривень на РЕБ — квиток на fwdays
@babichdev
Код на відчепись, чи відчепіться від мого коду?
У кожного був цей момент: задачу закрито, ревʼю пройдено, усе працює — але щось свербить. Може, ще трохи підчистити? Перейменувати функцію? Винести шматок у модуль? Просто, щоб було "красивіше".
Так ось це і є зіткнення перфекціонізму з "достатністю" — і саме тут починається наша розмова про Good Enough Code.
Good Enough Code — це не "аби працювало". Це не код "на відчепись". Це підхід, у якому рішення достатньо хороше, щоб працювати, не створювати надмірний технічний борг і не витрачати зайві дні на причесування уже робочого коду. Це про точку, за якою зусилля на покращення вже не виправдані вигодою.
У реальності більшість задач — це не архітектурні шедеври, а практичні компроміси. І намагання зробити "ідеально" часто шкодить більше, ніж допомагає. Час іде на дрібниці, фідбек затримується, команда буксує в ревʼю. Продукт стоїть. Користувач чекає.
Парадоксально, але заради якості ми нерідко жертвуємо користю. І саме підхід GEC повертає фокус туди, де він має бути — на цінність.
Хороший код — це той, що вирішує задачу по суті, читається та підтримується без пояснювальної бригади, не ламається при зміні й дозволяє рухатися далі. Не ідеальний, а достатньо хороший, щоб не зупиняти розробку.
В той же час це не виправдання ліні. Це усвідомлений вибір, коли ти розумієш, де точка diminishing returns, що вигідніше бізнесу, і куди справді варто спрямувати свою енергію.
Бо в щоденній розробці виграє не той, хто пише красиво. А той, хто доставляє результат — і вміє вчасно зупинитись.
Зацікавило? Тоді ставте вподобайки і діліться з друзями!
І якщо цей допис набере понад 150 реакцій та 1000 переглядів, то у наступних дописах ми з вами обовʼязково розглянемо:
– Як відрізнити достатній код від халтури?
– Які критерії “good enough”?
– Чому перфекціонізм — це теж технічний борг?
– Як впровадити цей підхід у команду й не перетворити все на безконтрольну лінь?
#good_enough_code #мислення_розробника
100 гривень на РЕБ — квиток на fwdays
@babichdev
❤200🔥49🤔4👏3
Друзі, у вас лишається лише доба на те, аби взяти участь у розіграші одного з двох Full Ticket квитків на JavaScript fwdays'25!
Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.
Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u
Номер картки банки
4441111125077309
Переможців обиратиму уже завтра, 21 травня, рандомом від monobank.
@babichdev
Усе, що треба — просто долучитися до збору на РЕБ для в/ч А3892.
Кожні 100 грн — ще один шанс виграти.
Фінальна ціль — 260 000 грн.
Посилання на банку
https://send.monobank.ua/jar/ABkKH6rr3u
Номер картки банки
4441111125077309
Переможців обиратиму уже завтра, 21 травня, рандомом від monobank.
@babichdev
🔥9
То null це обʼєкт чи не обʼєкт?!
Певен, ви не раз натрапляли на чергову добірку "приколів" в дусі "ха-ха, JavaScript тупий", в якій точно була згадка про те, що
На перший погляд. Але якщо копнути глибше, виявиться, що null це null, а причина такої поведінки typeof захована у глибині віків.
У ранній реалізації JavaScript оператор typeof не мав окремої перевірки на null. Він просто дивився: чи значення схоже на обʼєкт — тобто, чи є посиланням у памʼяті (pointer). А null тоді представлявся як 0x00 — класичний null pointer. Не буквальний, як у C, але концептуально споріднений: “порожнє місце”, що колись мало би бути посиланням.
І через те, що typeof не заглиблювався в перевірку, а лише умовно питав: «Чи це посилання?», то 0x00 сприймалося як “так” — і typeof null повертав "object".
Цю поведінку закріпили в ECMA-262, і пізніше вже не змогли виправити — занадто багато коду залежало від цього “багу”. А Брендан Айк прямо назвав таку поведінку помилкою: (1)
***
Ну а тепер — “ок, а нашо це нам?”. А ось навіщо: ця поведінка лишається актуальною. І банальна перевірка:
…пропустить null. І при звертанні до foo зловите класичний
Тому при перевірці на обʼєкт варто додавати й перевірку на "не null":
Ось такий цікавий "баг"-стандарт, що старіший за більшість сучасних веброзробників.
А ви стикалися з ним на практиці? Скільки ночей коштував вам пошук, чому код постійно падає від "Uncaught TypeError…"? Діліться в коментарях!
P.S. Так, так я знаю про оператор
***
Останній шанс виграти один з двох Full Ticket квитків на JS fwdays'25! Долучайся, донать 100 гривень і вигравай!
@babichdev
Певен, ви не раз натрапляли на чергову добірку "приколів" в дусі "ха-ха, JavaScript тупий", в якій точно була згадка про те, що
typeof null === 'object'. Хоча насправді null не object. Правда, тупо?На перший погляд. Але якщо копнути глибше, виявиться, що null це null, а причина такої поведінки typeof захована у глибині віків.
У ранній реалізації JavaScript оператор typeof не мав окремої перевірки на null. Він просто дивився: чи значення схоже на обʼєкт — тобто, чи є посиланням у памʼяті (pointer). А null тоді представлявся як 0x00 — класичний null pointer. Не буквальний, як у C, але концептуально споріднений: “порожнє місце”, що колись мало би бути посиланням.
І через те, що typeof не заглиблювався в перевірку, а лише умовно питав: «Чи це посилання?», то 0x00 сприймалося як “так” — і typeof null повертав "object".
Цю поведінку закріпили в ECMA-262, і пізніше вже не змогли виправити — занадто багато коду залежало від цього “багу”. А Брендан Айк прямо назвав таку поведінку помилкою: (1)
I said typeof null == “object” was a mistake because code that condition guards must null-test before dereferencing
***
Ну а тепер — “ок, а нашо це нам?”. А ось навіщо: ця поведінка лишається актуальною. І банальна перевірка:
if (typeof x === 'object') {
x.foo();
}…пропустить null. І при звертанні до foo зловите класичний
Uncaught TypeError: Cannot read properties of null.Тому при перевірці на обʼєкт варто додавати й перевірку на "не null":
typeof x === 'object' && x !== null
Ось такий цікавий "баг"-стандарт, що старіший за більшість сучасних веброзробників.
А ви стикалися з ним на практиці? Скільки ночей коштував вам пошук, чому код постійно падає від "Uncaught TypeError…"? Діліться в коментарях!
P.S. Так, так я знаю про оператор
?. і сам активно ним користуюсь. От набере цей допис 101 вподобайку, тоді й розглянемо, чи є цей оператор панацеєю від усіх null.***
Останній шанс виграти один з двох Full Ticket квитків на JS fwdays'25! Долучайся, донать 100 гривень і вигравай!
@babichdev
❤155🔥31🤔7👏5