То 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
Good Enough Code. ч.2
GEC ≠ халтура
[ч.1 | ч.3]
Часто можна почути: мовляв, “достатньо хороший код” — це просто красива назва для того, щоб зробити абияк. Проте, це не так.
Good Enough Code — це не про недбалість. Це про свідомий, зважений вибір з розумінням наслідків та прийняттям відповідальности за ці наслідки.
Халтурний код — це той, що погано читається, складний для змін, не має тестів і не витримує навіть базових вимог до якості. Він створює ризики, накопичує технічний борг і гальмує команду та продукт.
Good Enough Code, навпаки, спирається на здоровий інженерний розрахунок. Це рішення, яке працює на користь продукту: виконує свою задачу, не створює проблем у майбутньому й дозволяє рухатися далі. Без надмірної витрати часу на деталі, що не принесуть суттєвої додаткової цінності.
Як відрізнити достатній код від халтури?
Ключ — у мотивації та наслідках. Халтура — це “аби відчепилися”, без розуміння впливу. GEC — це “зроблено достатньо добре для цієї задачі”, з розрахунком на підтримку, ризики й фокус на результат.
І ось тут треба зрозуміти найголовніше: "достатньо добре" не існує без контексту.
GEC це не універсальний стандарт якості, це про відповідність якості обставинам:
– Якщо це скрипт, який разово пройде по CSV-шці для маркетологів — “достатньо” може означати “працює, не падає, зроблено за 20 хвилин”.
– Якщо це MVP — enough це коли ви можете за дві хвилини показати користувачеві цінність.
– Якщо ж ви пишете код для кардіостимулятора — “достатньо” означає верифікацію, сертифікацію та бездоганність.
Good Enough Code — це не компроміс заради компромісу. Це розуміння, де саме пролягає межа між "ще треба доробити" та "вже не має сенсу".
Цей підхід не про зменшення відповідальності, навпаки, він про її збільшення. Він про конкретний фокус в конкретний момент, але при цьому і про усвідомлення ширшої картини та розуміння, де так як можна зрізати кути, а де — не можна у жодному разі.
#good_enough_code #мислення_розробника
***
Наступного разу ми поговоримо про найбільшого ворога розробника — diminishing returns та чому більше часу далеко не завжди значить більше якості.
@babichdev
.
GEC ≠ халтура
[ч.1 | ч.3]
Часто можна почути: мовляв, “достатньо хороший код” — це просто красива назва для того, щоб зробити абияк. Проте, це не так.
Good Enough Code — це не про недбалість. Це про свідомий, зважений вибір з розумінням наслідків та прийняттям відповідальности за ці наслідки.
Халтурний код — це той, що погано читається, складний для змін, не має тестів і не витримує навіть базових вимог до якості. Він створює ризики, накопичує технічний борг і гальмує команду та продукт.
Good Enough Code, навпаки, спирається на здоровий інженерний розрахунок. Це рішення, яке працює на користь продукту: виконує свою задачу, не створює проблем у майбутньому й дозволяє рухатися далі. Без надмірної витрати часу на деталі, що не принесуть суттєвої додаткової цінності.
Як відрізнити достатній код від халтури?
Ключ — у мотивації та наслідках. Халтура — це “аби відчепилися”, без розуміння впливу. GEC — це “зроблено достатньо добре для цієї задачі”, з розрахунком на підтримку, ризики й фокус на результат.
І ось тут треба зрозуміти найголовніше: "достатньо добре" не існує без контексту.
GEC це не універсальний стандарт якості, це про відповідність якості обставинам:
– Якщо це скрипт, який разово пройде по CSV-шці для маркетологів — “достатньо” може означати “працює, не падає, зроблено за 20 хвилин”.
– Якщо це MVP — enough це коли ви можете за дві хвилини показати користувачеві цінність.
– Якщо ж ви пишете код для кардіостимулятора — “достатньо” означає верифікацію, сертифікацію та бездоганність.
Good Enough Code — це не компроміс заради компромісу. Це розуміння, де саме пролягає межа між "ще треба доробити" та "вже не має сенсу".
Цей підхід не про зменшення відповідальності, навпаки, він про її збільшення. Він про конкретний фокус в конкретний момент, але при цьому і про усвідомлення ширшої картини та розуміння, де так як можна зрізати кути, а де — не можна у жодному разі.
#good_enough_code #мислення_розробника
***
Наступного разу ми поговоримо про найбільшого ворога розробника — diminishing returns та чому більше часу далеко не завжди значить більше якості.
@babichdev
.
🔥70❤21🤔4👏2
This media is not supported in your browser
VIEW IN TELEGRAM
На неймовірно ламповій та затишній конференції JavaScript fwdays'25 розповідав про сигнали, що це таке, кому вони треба, і чому ми маємо знати про них вже.
Дякую глядачам за неймовірно теплий прийом )
P.S. Велика стаття про сигнали встала в чергу ;)
Дякую глядачам за неймовірно теплий прийом )
P.S. Велика стаття про сигнали встала в чергу ;)
❤85👏10
27 травня, Львів. Атляс. 19:00.
Жива дискусія про якість і швидкість у розробці.
Я — за Good Enough Code. Роман Марінський — за Clean Code. За філіжанкою (не)кави шукатимемо істину та обговоримо переваги й недоліки обох підходів.
Квиточки: https://secure.wayforpay.com/payment/cctd_vs_gec
Усі гривні — на ЗСУ.
Чекатиму на вас.
@babichdev
Жива дискусія про якість і швидкість у розробці.
Я — за Good Enough Code. Роман Марінський — за Clean Code. За філіжанкою (не)кави шукатимемо істину та обговоримо переваги й недоліки обох підходів.
Квиточки: https://secure.wayforpay.com/payment/cctd_vs_gec
Усі гривні — на ЗСУ.
Чекатиму на вас.
@babichdev
🔥24❤6
Symbol, на мою особисту думку — найзагадковіший тип даних у JavaScript. Механізм його роботи не схожий на інші примітиви, а суть існування стає ясною лише після переходу на наступний енергетичний рівень буття.
Що таке Symbol? Для чого він? Які задачі вирішує? Гайда розбиратися.
Символи — це особливі примітиви, які гарантують максимальну унікальність значення. Настільки максимальну, що
Символи дозволяють уникати конфліктів у ключах обʼєкта. Навіть якщо у вас символздєсь і символздєсь — це завжди різні значення. Ви можете абсолютно спокійно робити таке (тільки от нашо?):
А доступитися до конкретної властивості, захованої за символом, можна тільки маючи посилання на сам символ.
Найскладніше в роботі з Symbol — це прийняти, що вони поводяться інакше, ніж звичні примітиви. Рядки, числа, логічні значення — змінюються, копіюються, порівнюються напряму. Символи ж — щось з квантової механіки, коли це ніби і примітив, а водночас і значення за посиланням. І якщо загубити його — то вже не знайти, бо створити такий самий буде неможливо (ну майже).
Символи неперелічувані — їх не видно в Object.keys, for...in, JSON.stringify. Але можна дістати через Object.getOwnPropertySymbols(obj) або Object.getOwnPropertyDenoscriptors(obj).
Це тому, що символи створені не для приватности як такої, а, радше, для прихованости та запобіганню випадкових перевизначень. Тобто часткової приватности.
До речі, про унікальність. Існує API Symbol.for(), яке дозволяє створювати загальнодоступні символи з єдиною ідентичністю, які зберігаються в глобальному реєстрівійськовозобовʼязаних:
Також існують так звані well-known Symbols, які працюють як API-хуки: ті ж Symbol.iterator, Symbol.toStringTag, які дозволяють описувати власні імплементації для певних поведінок. Наприклад, описавши метод [Symbol.iterator] у класі або обʼєкті, ми зробимо такий обʼєкт Iterable.
Швидше за все, ви не будете стикатися з ними щодня. Хіба ви розробляєте якусь бібліотеку або рішення, в якому надзвичайно важлива інкапсуляція на рівні обʼєктів.
🔗 MDN
Зізнавайтесь, хоч трошки зрозуміли, що таке Symbol? І обовʼязково поділіться своїм досвідом роботи з ним в коментарях (навіть якщо й не зрозуміли)!
@babichdev
Вподобайки, поширення — я про це вже не мав би вам нагадувать ;)
***
📣 Нагадую, що завтра (27.05) чекатиму вас на затишній дискусії про Clean Code vs Good Enough Code у Львові! Приходьте самі та запрошуйте колег!
Що таке Symbol? Для чого він? Які задачі вирішує? Гайда розбиратися.
Символи — це особливі примітиви, які гарантують максимальну унікальність значення. Настільки максимальну, що
Symbol('foo') !== Symbol('foo'). Оця текстова мітка — по суті просто ваша примітка до змінної, а не частина самого значення.Символи дозволяють уникати конфліктів у ключах обʼєкта. Навіть якщо у вас символздєсь і символздєсь — це завжди різні значення. Ви можете абсолютно спокійно робити таке (тільки от нашо?):
const object = {
[Symbol("підпиздєсь")]: "foo",
[Symbol("підпиздєсь")]: "bar"
};А доступитися до конкретної властивості, захованої за символом, можна тільки маючи посилання на сам символ.
Symbol — це єдиний примітив, який можна використовувати як ключ до обʼєкта без перетворення на рядок. Інші примітиви, як-от числа чи булеві значення, автоматично зводяться до рядків.
Найскладніше в роботі з Symbol — це прийняти, що вони поводяться інакше, ніж звичні примітиви. Рядки, числа, логічні значення — змінюються, копіюються, порівнюються напряму. Символи ж — щось з квантової механіки, коли це ніби і примітив, а водночас і значення за посиланням. І якщо загубити його — то вже не знайти, бо створити такий самий буде неможливо (ну майже).
Символи неперелічувані — їх не видно в Object.keys, for...in, JSON.stringify. Але можна дістати через Object.getOwnPropertySymbols(obj) або Object.getOwnPropertyDenoscriptors(obj).
Це тому, що символи створені не для приватности як такої, а, радше, для прихованости та запобіганню випадкових перевизначень. Тобто часткової приватности.
До речі, про унікальність. Існує API Symbol.for(), яке дозволяє створювати загальнодоступні символи з єдиною ідентичністю, які зберігаються в глобальному реєстрі
const here = Symbol.for('підпиздєсь');
const there = Symbol.for('підпиздєсь');
console.log(here === there); // trueТакож існують так звані well-known Symbols, які працюють як API-хуки: ті ж Symbol.iterator, Symbol.toStringTag, які дозволяють описувати власні імплементації для певних поведінок. Наприклад, описавши метод [Symbol.iterator] у класі або обʼєкті, ми зробимо такий обʼєкт Iterable.
Швидше за все, ви не будете стикатися з ними щодня. Хіба ви розробляєте якусь бібліотеку або рішення, в якому надзвичайно важлива інкапсуляція на рівні обʼєктів.
🔗 MDN
Зізнавайтесь, хоч трошки зрозуміли, що таке Symbol? І обовʼязково поділіться своїм досвідом роботи з ним в коментарях (навіть якщо й не зрозуміли)!
@babichdev
Вподобайки, поширення — я про це вже не мав би вам нагадувать ;)
***
📣 Нагадую, що завтра (27.05) чекатиму вас на затишній дискусії про Clean Code vs Good Enough Code у Львові! Приходьте самі та запрошуйте колег!
❤74🔥20🤔9
Good Enough Code, ч.3 — Diminishing returns
[ч.2] | [ч.4]
Що найбільше заважає нам у розробці? Звісно, ми самі. Але сьогодні мова про більш конкретного ворога — diminishing returns.
До прикладу, вам до рук потрапляє якийсь модуль, який вам за першу ітерацію вдається оптимізувати, припустимо, на 50% — з 400мс до 200мс. Наступні дві ітерації дають ще 10% — з 200мс до 180, потім ще 10%, вже до 162. Але зусиль — утричі більше.
Вигода, очевидно, занадто мала, тенденція ж — очевидна. А якщо рахувати загальну вигоду, то від початкового стану ви виграли за першу ітерацію цілих 50%, а за усі три ітерації разом — 59,5%. Тобто в результаті додаткових зусиль ви не виграли й десяти відсотків.
Звісно, цей приклад досить спрощений, однак чудово ілюструє принцип diminishing returns. Ви вкладаєте усе більше часу, отримуючи усе менше реального результату. Ба більше, на практиці часто якраз ось ці додаткові зусилля привносять ще й нестабільність до системи, збільшуючи її схильність до помилок та вартість подальшої підтримки.
Як зловити себе? Ви витрачаєте непомірно більше часу на удосконалення рішення, аніж на саме рішення. Більш явна ознака — команда не розуміє доцільність вашого затягування (це вже навіть не дзвіночок, це великодній дзвін). Або ж ви просто не можете зупинитись і починаєте полірувати заради самого полірування — впадаючи в азарт, попри мізерний ефект.
Ось тут вперше й прозвучить головна ідея усієї концепції Good Enough Code:
"Час від часу випускайте на волю свого внутрішнього Януковича, який казатиме вам “АСТАНАВІТЄСЬ“".
Вкрай важливо розуміти, коли ваше пакращення уже не буде пакращенням. Якщо ви намагаєтесь досягти прискорення вашого алгоритму на 2мс у фінансовому застосунку — це абсолютно виправдано. Там це може означати втрачені мільйони. Але якщо ви третій тиждень поліруєте форму на п’ять полів, щоб кнопка Submit спрацьовувала на 20мс швидше — це марно згаяний час. Користувач не помітить різниці.
Оцінюючи diminishing returns надзвичайно важливо брати до уваги не лише конкретні цифри, метрики й показники, а й доцільність покращень. Доречність витрати часу. Не кожне покращення — виправдане. Однак кожна зайва складність має ціну.
Не все потребує покращення. Я знаю, цю думку складно прийняти. Ще раз: не все потребує покращення. Але усе потребує стабільности. Про що ми й поговоримо наступного разу.
Якщо вам дуже сподобався цей допис, звичайно.
@babichdev
Дуже цікаво дізнатися вашу думку щодо diminishing returns — згодні, не згодні, вважаєте це проблемою чи вигадкою? Ласкаво прошу до дискусії!
#good_enough_code
[ч.2] | [ч.4]
Що найбільше заважає нам у розробці? Звісно, ми самі. Але сьогодні мова про більш конкретного ворога — diminishing returns.
До прикладу, вам до рук потрапляє якийсь модуль, який вам за першу ітерацію вдається оптимізувати, припустимо, на 50% — з 400мс до 200мс. Наступні дві ітерації дають ще 10% — з 200мс до 180, потім ще 10%, вже до 162. Але зусиль — утричі більше.
Вигода, очевидно, занадто мала, тенденція ж — очевидна. А якщо рахувати загальну вигоду, то від початкового стану ви виграли за першу ітерацію цілих 50%, а за усі три ітерації разом — 59,5%. Тобто в результаті додаткових зусиль ви не виграли й десяти відсотків.
Звісно, цей приклад досить спрощений, однак чудово ілюструє принцип diminishing returns. Ви вкладаєте усе більше часу, отримуючи усе менше реального результату. Ба більше, на практиці часто якраз ось ці додаткові зусилля привносять ще й нестабільність до системи, збільшуючи її схильність до помилок та вартість подальшої підтримки.
Як зловити себе? Ви витрачаєте непомірно більше часу на удосконалення рішення, аніж на саме рішення. Більш явна ознака — команда не розуміє доцільність вашого затягування (це вже навіть не дзвіночок, це великодній дзвін). Або ж ви просто не можете зупинитись і починаєте полірувати заради самого полірування — впадаючи в азарт, попри мізерний ефект.
Ось тут вперше й прозвучить головна ідея усієї концепції Good Enough Code:
"Час від часу випускайте на волю свого внутрішнього Януковича, який казатиме вам “АСТАНАВІТЄСЬ“".
Вкрай важливо розуміти, коли ваше пакращення уже не буде пакращенням. Якщо ви намагаєтесь досягти прискорення вашого алгоритму на 2мс у фінансовому застосунку — це абсолютно виправдано. Там це може означати втрачені мільйони. Але якщо ви третій тиждень поліруєте форму на п’ять полів, щоб кнопка Submit спрацьовувала на 20мс швидше — це марно згаяний час. Користувач не помітить різниці.
Оцінюючи diminishing returns надзвичайно важливо брати до уваги не лише конкретні цифри, метрики й показники, а й доцільність покращень. Доречність витрати часу. Не кожне покращення — виправдане. Однак кожна зайва складність має ціну.
Не все потребує покращення. Я знаю, цю думку складно прийняти. Ще раз: не все потребує покращення. Але усе потребує стабільности. Про що ми й поговоримо наступного разу.
Якщо вам дуже сподобався цей допис, звичайно.
@babichdev
Дуже цікаво дізнатися вашу думку щодо diminishing returns — згодні, не згодні, вважаєте це проблемою чи вигадкою? Ласкаво прошу до дискусії!
#good_enough_code
🔥73❤19👏1
Як "вимкнути" частину форми?
Доволі часто перед нами постає задача "вимкнути", або ж задізейблити відразу цілу частину форми, а не один якийсь інпут. Не знаю, як ви, а я часто вимикав усі контроли по одному.
А виявляється, що це можна зробити за допомогою атрибуту disabled елемента fieldset! Якщо встановити значення цього артибуту у правдиве значення, то усі вкладені в цей fieldset інтерактивні елементи заблокуються. І інпути, і кнопки, і селекти. Все.
Але існує запасне рішення на той випадок, якщо вам потрібно, до прикладу, залишити якийсь елемент активним. Наприклад, кнопку "Редагувати". Тоді ви можете її помістити до вкладеного legend, всередині якого закони й правила не діють. Ну, як мінімум, батьківський disabled ігнорується.
Мені ця фіча точно стане в нагоді, а що скажете на це ви? Чи мали в практиці випадки, коли це могло б спростити ваш код? Розкажіть!
@babichdev
Цікаво? Корисно? Тисни вподобайку та ділися дописом з друзями та колегами!
Доволі часто перед нами постає задача "вимкнути", або ж задізейблити відразу цілу частину форми, а не один якийсь інпут. Не знаю, як ви, а я часто вимикав усі контроли по одному.
А виявляється, що це можна зробити за допомогою атрибуту disabled елемента fieldset! Якщо встановити значення цього артибуту у правдиве значення, то усі вкладені в цей fieldset інтерактивні елементи заблокуються. І інпути, і кнопки, і селекти. Все.
Але існує запасне рішення на той випадок, якщо вам потрібно, до прикладу, залишити якийсь елемент активним. Наприклад, кнопку "Редагувати". Тоді ви можете її помістити до вкладеного legend, всередині якого закони й правила не діють. Ну, як мінімум, батьківський disabled ігнорується.
<fieldset disabled>
<legend>
Legend
<button>Edit</button>
</legend>
<input>
<button>Click me</button>
</fieldset>
Мені ця фіча точно стане в нагоді, а що скажете на це ви? Чи мали в практиці випадки, коли це могло б спростити ваш код? Розкажіть!
@babichdev
Цікаво? Корисно? Тисни вподобайку та ділися дописом з друзями та колегами!
🔥95👏5❤4
#ДонатНаРЕБ
Збір для 109 ОГШБ 10 ОГШБр "Едельвейс"
Друзі, потрібно зібрати 100 000 гривень для дооплати засобу радіоелектронної боротьби для 109 окремого гірсько-штурмового батальйону. Більшу частину рахунку вже сплачено — залишилось добити фінал.
Щоб заохотити вас долучатися трохи активніше — я запускаю розіграш! За кожні 50 гривень донату ви отримуєте шанс виграти один із подарунків:
🎁 Пазл GoodLoot "Witcher: Griffin Fight"
Подарунок від мене особисто
🎯 Мета: 20 000 грн
🎁 Клавіатура R-Go Compact Break
Від друзів з ERGO PLACE
🎯 Мета: 50 000 грн
🎁 LEGO Dune Atreides Royal Ornithopter
Від української продуктової IT-компанії Brainstack
🎯 Мета: 100 000 грн
Щойно досягаємо відповідної мети — розігрую черговий подарунок серед усіх донатерів за допомогою monobank.
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Памʼятайте: не існує замалих донатів.
Кожен ваш внесок — це ще один збитий дрон.
Ще одне збережене життя.
Ще один крок до Перемоги.
Збір для 109 ОГШБ 10 ОГШБр "Едельвейс"
Друзі, потрібно зібрати 100 000 гривень для дооплати засобу радіоелектронної боротьби для 109 окремого гірсько-штурмового батальйону. Більшу частину рахунку вже сплачено — залишилось добити фінал.
Щоб заохотити вас долучатися трохи активніше — я запускаю розіграш! За кожні 50 гривень донату ви отримуєте шанс виграти один із подарунків:
🎁 Пазл GoodLoot "Witcher: Griffin Fight"
Подарунок від мене особисто
🎯 Мета: 20 000 грн
🎁 Клавіатура R-Go Compact Break
Від друзів з ERGO PLACE
🎯 Мета: 50 000 грн
🎁 LEGO Dune Atreides Royal Ornithopter
Від української продуктової IT-компанії Brainstack
🎯 Мета: 100 000 грн
Щойно досягаємо відповідної мети — розігрую черговий подарунок серед усіх донатерів за допомогою monobank.
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Памʼятайте: не існує замалих донатів.
Кожен ваш внесок — це ще один збитий дрон.
Ще одне збережене життя.
Ще один крок до Перемоги.
🔥12❤3
Гра у хованки
Одна з найпоширеніших задач в розробці інтерфейсів — тимчасово приховати той чи інший елемент. І рішення, здавалось би, очевидне — зробити
Ну, в більшості випадків може й так, але чи універсальне це рішення? Давайте спробуємо розібратися.
Приховати елемент можна у кілька способів, і вже згаданий
А є
Чи згадати тоді про атрибут
А ви як, користуєтесь цими можливостями, чи не задумуючись, просто викидаєте елемент з DOM?
@babichdev
***
Приєднуйтесь до збору на РЕБ та вигравайте чудові подарунки від мене та моїх друзів!
Одна з найпоширеніших задач в розробці інтерфейсів — тимчасово приховати той чи інший елемент. І рішення, здавалось би, очевидне — зробити
display: none, та й по всьому.Ну, в більшості випадків може й так, але чи універсальне це рішення? Давайте спробуємо розібратися.
Приховати елемент можна у кілька способів, і вже згаданий
display: none впевнено утримує першість. Коли ми застосовуємо цю властивість до елементу, він "зникає" з потоку документа, припиняючи брати участь в побудові рендер-дерева і, відповідно, візуального макету сторінки, так званого layout. При цьому з DOM він нікуди не зникає. Якщо коротко, то display: none прибирає усі видимі сліди присутности елемента.А є
visibility: hidden. І тут постає питання — а в чому ж різниця? А різниця в тому, що ця властивість прибирає лише відображення елемента, але його місце в render tree та layout зберігається. На сторінці при цьому утворюється "дірка" на місці цього елемента.display: none нагадує магічний трюк зі зникненням, але з кінострічки "Престиж": елемент дійсно зникає, не припиняючи свого існування. Чи?.. Але це вже інше питання. А от visibility: hidden це як той же трюк, але в актовій залі вашої школи: елемент від вас просто затуляють білим простирадлом, усі знають, що він там, а крайні ряди навіть можуть трошки його побачити.Чи згадати тоді про атрибут
hidden? Хіба побіжно. Бо це просто ще один спосіб приховати за допомогою <div hidden> чи el.hidden = true. Але тільки у тому випадку, якщо ви не перевизначили стилі для селектора [hidden], який браузери за замовчуванням стилізують як display: none. А ви можете, я знаю.А ви як, користуєтесь цими можливостями, чи не задумуючись, просто викидаєте елемент з DOM?
@babichdev
***
Приєднуйтесь до збору на РЕБ та вигравайте чудові подарунки від мене та моїх друзів!
❤53🔥13🤔6👏3
Друзі, запрошую вас на Стрим для своїх №3!
Що це? Це затишно й по-дружньому проведений разом з вами вечір неділі і чудова нагода поставити мені запитання, на яке я можу дати як розлогу відповідь, варту цілого відео, так і вкластися в одне речення )
Досі тривожить, чи прийдесіренький вовчок ШІ і забере роботу? Цікавить, чому я не вважаю React найкращим у світі інструментом? Хочете зрозуміти, як рухатись далі в карʼєрі? Словом — питайте мене що завгодно, а я з радістю відповім вам наживо уже цієї неділі, 1 червня, о 18:00 на закритому Стримі для своїх!
Тож готуйте свої питання і реєструйтесь. До речі, реєстрація потрібна лише для того, аби ви могли додати подію до свого календаря. Я поки ніяких розсилок не планую ) Поки ;)
Чекатиму на вас!
Стрим для своїх №3
01 червня 2025, 18:00
Реєструйтесь тут: https://streamyard.com/watch/rYCqYEfzf5x9
А ще під час стриму я розіграю позачерговий подарунок за донати у зборі на РЕБ.
Що це? Це затишно й по-дружньому проведений разом з вами вечір неділі і чудова нагода поставити мені запитання, на яке я можу дати як розлогу відповідь, варту цілого відео, так і вкластися в одне речення )
Досі тривожить, чи прийде
Тож готуйте свої питання і реєструйтесь. До речі, реєстрація потрібна лише для того, аби ви могли додати подію до свого календаря. Я поки ніяких розсилок не планую ) Поки ;)
Чекатиму на вас!
Стрим для своїх №3
01 червня 2025, 18:00
Реєструйтесь тут: https://streamyard.com/watch/rYCqYEfzf5x9
А ще під час стриму я розіграю позачерговий подарунок за донати у зборі на РЕБ.
StreamYard
Стрим для своїх №3
You've been invited to join this webinar!
🔥21❤6
Гра в хованки 2: Швидкодія завдає удару у відповідь
В коментарях до попереднього допису про display vs visibility ви ніби жартома згадали opacity. Чи не згадав я про нього незаслужено? Дивіться, цей спосіб вирізняється однією суттєвою деталлю: навіть будучи повністю "невидимим", а по факту просто прозорим, елемент повністю зберігає всю інтерактивність — фокусабельність, події клавіатури й миші, а ще залишається повністю "видимим" скрінрідерів.
І зі скрінрідерами така історія, що майже усі способи направду сховають елемент від них, окрім того самого opacity. З ним вам доведеться вручну додавати атрибут aria-hidden. Тому жарти жартами, а a11y в сучасному світі треба знати й практикувати.
А що зі швидкодією?
Ховаючи елемент, нам важливо знати дві речі: як він поводитиметься зі скрінрідерами та скільки "коштуватиме" його відновлення.
І на це впливає в першу чергу те, чи викликатиметься reflow — процес перерахунку макету з видимих елементів. Цей процес насправді надзвичайно легко викликати, достатньо змінити будь-яку властивість елемента, що відповідає за його "фізичну" поведінку: розміри чи відступи. Ну і, очевидно, display.
Не вдаючись в подробиці, зазначу, що цей процес тим затратніший, чим більше у вас елементів у render-tree. Однак при цьому не найзатратніший, бо при цьому не змінюється DOM.
А от visibility та opacity reflow не викликатимуть, бо вони не змінюють жодних "фізичних" параметрів елемента, тож їх застосування викличе лише repaint. А він, у свою чергу, достатньо швидкий і давно дуууже сильно оптимізований бравзерами.
DOM оновлювати дорого
А от якщо ви любите стріляти по горобцях з BFG, то, швидше за все, ви користуєтесь "умовним рендерингом" вашого улюбленого фреймворку чи бібліотеки. Чи це погано, запитаєте ви? It depends, відповім я.
На маленьких і нечастих рендерах то вже бог з ним, там втрата тої швидкодії фактично непомітна. А от коли ви таке практикуєте на частих оновленнях, або на великій кількості елементів, то ось час вас присоромити.
Вся справа в тому, що умовний рендеринг зазвичай просто видаляє/вставляє елементи з DOM. І попри усі намагання оптимізувати ці процеси, маніпуляції з DOM були, лишаються й будуть найдорожчими в світі.
Майже кожна, навіть найменша зміна в DOM (а, тим паче, видалення/додавання елемента) потребує перевиконання повного циклу:
1. Оновити DOM
1¾. Оновити CSSOM (якщо змінили інлайн-стилі)
2. Оновити render-tree
3. Виконати reflow
4. Виконати repaint
Знову ж таки, оптимізації, батчинг, та-та, чули, знаєм. Але усе одно оновлення DOM — дороге. І викликатиме дуууже помітні лаги, якщо ви одночасно ховаєте або показуєте багато елементів.
У мене колись давно в практиці була задача з кастомним багаторівневим акордеоном, і виявилося, що ховати секції з display: none набагато швидше, аніж з класичним conditional rendering. Так, лаги усе одно були, але значно менші.
Тож підібʼємо підсумок: не всі "хованки" однаково корисні.
display: none і умовний рендеринг справді прибирають елемент із рендер-дерева, але коштом повної перебудови макету, а conditional rendering так і взагалі за рахунок зміни структури DOM. visibility: hidden і opacity: 0 лишають елемент у потоці, але поводяться зовсім по-різному з погляду доступности та взаємодії. Перший — неактивний і “німіє”, другий — поводиться як повноцінний видимий елемент, просто невидимий.
І лише розуміючи ці відмінності, можна ефективно керувати поведінкою інтерфейсу, не жертвуючи швидкодією та доступністю.
***
Ви вже долучилися до збору на РЕБ? Усього 50 гривень і шанс виграти класні подарунки — ваш!
В коментарях до попереднього допису про display vs visibility ви ніби жартома згадали opacity. Чи не згадав я про нього незаслужено? Дивіться, цей спосіб вирізняється однією суттєвою деталлю: навіть будучи повністю "невидимим", а по факту просто прозорим, елемент повністю зберігає всю інтерактивність — фокусабельність, події клавіатури й миші, а ще залишається повністю "видимим" скрінрідерів.
І зі скрінрідерами така історія, що майже усі способи направду сховають елемент від них, окрім того самого opacity. З ним вам доведеться вручну додавати атрибут aria-hidden. Тому жарти жартами, а a11y в сучасному світі треба знати й практикувати.
А що зі швидкодією?
Ховаючи елемент, нам важливо знати дві речі: як він поводитиметься зі скрінрідерами та скільки "коштуватиме" його відновлення.
І на це впливає в першу чергу те, чи викликатиметься reflow — процес перерахунку макету з видимих елементів. Цей процес насправді надзвичайно легко викликати, достатньо змінити будь-яку властивість елемента, що відповідає за його "фізичну" поведінку: розміри чи відступи. Ну і, очевидно, display.
Не вдаючись в подробиці, зазначу, що цей процес тим затратніший, чим більше у вас елементів у render-tree. Однак при цьому не найзатратніший, бо при цьому не змінюється DOM.
А от visibility та opacity reflow не викликатимуть, бо вони не змінюють жодних "фізичних" параметрів елемента, тож їх застосування викличе лише repaint. А він, у свою чергу, достатньо швидкий і давно дуууже сильно оптимізований бравзерами.
Я відчуваю гостру необхідність зануритись разом із вами в процес відображення сторінки бравзером, а саме розібрати усі ці дерева, та як вони між собою повʼязані. Що скажете? 100 вподобайок вистачить?
DOM оновлювати дорого
А от якщо ви любите стріляти по горобцях з BFG, то, швидше за все, ви користуєтесь "умовним рендерингом" вашого улюбленого фреймворку чи бібліотеки. Чи це погано, запитаєте ви? It depends, відповім я.
На маленьких і нечастих рендерах то вже бог з ним, там втрата тої швидкодії фактично непомітна. А от коли ви таке практикуєте на частих оновленнях, або на великій кількості елементів, то ось час вас присоромити.
Вся справа в тому, що умовний рендеринг зазвичай просто видаляє/вставляє елементи з DOM. І попри усі намагання оптимізувати ці процеси, маніпуляції з DOM були, лишаються й будуть найдорожчими в світі.
Майже кожна, навіть найменша зміна в DOM (а, тим паче, видалення/додавання елемента) потребує перевиконання повного циклу:
1. Оновити DOM
1¾. Оновити CSSOM (якщо змінили інлайн-стилі)
2. Оновити render-tree
3. Виконати reflow
4. Виконати repaint
Знову ж таки, оптимізації, батчинг, та-та, чули, знаєм. Але усе одно оновлення DOM — дороге. І викликатиме дуууже помітні лаги, якщо ви одночасно ховаєте або показуєте багато елементів.
У мене колись давно в практиці була задача з кастомним багаторівневим акордеоном, і виявилося, що ховати секції з display: none набагато швидше, аніж з класичним conditional rendering. Так, лаги усе одно були, але значно менші.
Тож підібʼємо підсумок: не всі "хованки" однаково корисні.
display: none і умовний рендеринг справді прибирають елемент із рендер-дерева, але коштом повної перебудови макету, а conditional rendering так і взагалі за рахунок зміни структури DOM. visibility: hidden і opacity: 0 лишають елемент у потоці, але поводяться зовсім по-різному з погляду доступности та взаємодії. Перший — неактивний і “німіє”, другий — поводиться як повноцінний видимий елемент, просто невидимий.
І лише розуміючи ці відмінності, можна ефективно керувати поведінкою інтерфейсу, не жертвуючи швидкодією та доступністю.
***
Ви вже долучилися до збору на РЕБ? Усього 50 гривень і шанс виграти класні подарунки — ваш!
❤75🔥9👏5
#цього_тижня ми з вами дізналися багато нового і зробили багато корисного! Дивіться самі:
— В понеділок спробували зрозуміти, що таке Symbol в JS;
— У вівторок продовжили подорож до Good Enough Code, розглянувши що таке diminishing returns;
— В середу дізналися, як вимикати відразу цілу частину форми з fieldset;
— В четвер нагадали собі про різні способи сховати елемент на сторінці;
— У пʼятницю ж відразу порівняли, які з них псують швидкодію найбільше;
А також розпочали збір на 100 000 гривень для 109 ОГШБ 10 ОГШБр "Едельвейс", — і кожен донат бере участь у розіграші подарунків!
***
А завершимо ми цей тиждень завтра на Стримі для своїх №3. Буду радий бачити кожного з вас!
— В понеділок спробували зрозуміти, що таке Symbol в JS;
— У вівторок продовжили подорож до Good Enough Code, розглянувши що таке diminishing returns;
— В середу дізналися, як вимикати відразу цілу частину форми з fieldset;
— В четвер нагадали собі про різні способи сховати елемент на сторінці;
— У пʼятницю ж відразу порівняли, які з них псують швидкодію найбільше;
А також розпочали збір на 100 000 гривень для 109 ОГШБ 10 ОГШБр "Едельвейс", — і кожен донат бере участь у розіграші подарунків!
***
А завершимо ми цей тиждень завтра на Стримі для своїх №3. Буду радий бачити кожного з вас!
🔥28❤7
Друзі, Стрим для своїх розпочнеться уже за лічені хвилини!
Відповідатиму на ваші питання, а ще зберемо кілька гривень на наш збір.
Ну і відмітимо успіх операції "Шалена бджілка" від СБУ ;)
Чекаю на вас!
P.S. Без реєстрації та СМС
Відповідатиму на ваші питання, а ще зберемо кілька гривень на наш збір.
Ну і відмітимо успіх операції "Шалена бджілка" від СБУ ;)
Чекаю на вас!
P.S. Без реєстрації та СМС
StreamYard
Стрим для своїх №3
You've been invited to join this webinar!
🔥10
Обіцянка-цяцянка, а потім — resolve
Promise давно вже міцно увійшов до нашої практики, а багато хто з вас навіть і не знає, як це — писати усе на вкладених колбеках. Та все ж більшість із нас продовжує писати код з "обіцянками" по-старому:
Тобто ми створюємо проміс, всередині робимо щось асинхронне, а тоді вже там же, всередині, і обробляємо результати виконання. Відверто, структурно це все ще схоже на маленький, але цілком відчутний callback-hell.
А як я вам скажу, що вже давно (і справді давно, включений до Baseline 2024 року) існує спосіб писати подібний код у більш структурованому, імперативному стилі? Дивіться:
Тут створюється порожній проміс і зберігаються посилання на resolve/reject. Що це дає? Місце виклику resolve/reject (наприклад, setTimeout) може бути деінде, ба більше, ви можете спокійно повертати чи передавати їх куди заманеться. Коли логіка створення проміса й обробки його результату відокремлені, код стає набагато гнучкішим.
Такий підхід згодиться, коли треба створити проміс зараз, а виконати його пізніше — наприклад, у зовнішньому евент-хендлері чи колбеках.
Promise.withResolvers не робить нічого революційного, по суті він є синтаксичним цукром для популярного патерна з “зовнішнім” resolve/reject:
Навіщо це особисто вам:
— Promise.withResolvers() — це зручний і безпечний спосіб створити проміс із доступом до resolve/reject ззовні;
— Він не привносить нової складности, навпаки просто формалізує та спрощує те, що ми й так давно робили руками;
— Дозволяє писати чистіший, зрозуміліший та структурованіший код, особливо у випадках, де логіка розірвана в часі.
Мені особисто дуже зайшло використовувати withResolvers, хоча б через дещо інший спосіб організації коду.
MDN
А ви як? Спробували би це у своєму проді? Чи може встигли вже? Розкажіть в коментарях!
@babichdev
***
👋 Збір на РЕБ для 109 ОГШБ 10 ОГШБр «Едельвейс» триває! Ми вже подолали першу позначку в 20 000 і впевнено йдемо до 50 000 грн! Кожні 50 грн — шанс виграти подарунок і допомогти ЗСУ.
Promise давно вже міцно увійшов до нашої практики, а багато хто з вас навіть і не знає, як це — писати усе на вкладених колбеках. Та все ж більшість із нас продовжує писати код з "обіцянками" по-старому:
const wait = (ms) =>
new Promise((resolve) => {
setTimeout(() => {
resolve('Готово!');
}, ms);
});
await wait(1000); // Через секунду → "Готово!"
Тобто ми створюємо проміс, всередині робимо щось асинхронне, а тоді вже там же, всередині, і обробляємо результати виконання. Відверто, структурно це все ще схоже на маленький, але цілком відчутний callback-hell.
А як я вам скажу, що вже давно (і справді давно, включений до Baseline 2024 року) існує спосіб писати подібний код у більш структурованому, імперативному стилі? Дивіться:
const { promise, resolve } = Promise.withResolvers();
setTimeout(() => {
resolve('Готово!');
}, 1000);
await promise; // → "Готово!"Тут створюється порожній проміс і зберігаються посилання на resolve/reject. Що це дає? Місце виклику resolve/reject (наприклад, setTimeout) може бути деінде, ба більше, ви можете спокійно повертати чи передавати їх куди заманеться. Коли логіка створення проміса й обробки його результату відокремлені, код стає набагато гнучкішим.
Такий підхід згодиться, коли треба створити проміс зараз, а виконати його пізніше — наприклад, у зовнішньому евент-хендлері чи колбеках.
Цей допис точно заслужив на твою вподобайку. От і постав її просто зараз ;)
Promise.withResolvers не робить нічого революційного, по суті він є синтаксичним цукром для популярного патерна з “зовнішнім” resolve/reject:
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
//
resolve();
Навіщо це особисто вам:
— Promise.withResolvers() — це зручний і безпечний спосіб створити проміс із доступом до resolve/reject ззовні;
— Він не привносить нової складности, навпаки просто формалізує та спрощує те, що ми й так давно робили руками;
— Дозволяє писати чистіший, зрозуміліший та структурованіший код, особливо у випадках, де логіка розірвана в часі.
Мені особисто дуже зайшло використовувати withResolvers, хоча б через дещо інший спосіб організації коду.
MDN
А ви як? Спробували би це у своєму проді? Чи може встигли вже? Розкажіть в коментарях!
@babichdev
***
Please open Telegram to view this post
VIEW IN TELEGRAM
❤109🔥25👏6
#партнерський_допис
Я на 100% впевнений, що серед вас немає нікого, хто бодай раз не робив git push (чули ви про про нього то точно), після якого щось там крутиться, скрипить, зеленіє, червоніє, падає, встає — і от ваш код уже в “проді”, де тисячі користувачів тиснуть ту саму “зільону кнопку”.
А ви цікавилися, що ж там скрипить-рипить і падає після пушу? Чи знаєте, як налаштувати хоча б простий CI/CD? А що, коли пайплайни почнуть падати один за одним — зрозумієте, в чому причина?
Я не кажу, що всі мають ставати DevOps-інженерами, але знати ці основи — то вже базова частина навичок розробника. Ваших навичок.
Саме тому щиро раджу подію, на якій ви дізнаєтеся трошки більше, а саме
DevOps: Від Кодування до Хмари — безкоштовний мітап від Sigma Software University.
📅 3 червня, 18:30
🌐 Онлайн
🎯 У програмі: Linux, Git, Docker, AWS, CI/CD — і головне, практичний кейс, де все це працює разом.
Цей мітап буде корисним для тих, хто хоче бачити свою роботу системніше, а особливо — мідлам, які прагнуть стати синьйорами, а не просто записати в резюме черговий фреймворк.
✅ РЕЄСТРАЦІЯ НА МІТАП
.
Я на 100% впевнений, що серед вас немає нікого, хто бодай раз не робив git push (чули ви про про нього то точно), після якого щось там крутиться, скрипить, зеленіє, червоніє, падає, встає — і от ваш код уже в “проді”, де тисячі користувачів тиснуть ту саму “зільону кнопку”.
А ви цікавилися, що ж там скрипить-рипить і падає після пушу? Чи знаєте, як налаштувати хоча б простий CI/CD? А що, коли пайплайни почнуть падати один за одним — зрозумієте, в чому причина?
Я не кажу, що всі мають ставати DevOps-інженерами, але знати ці основи — то вже базова частина навичок розробника. Ваших навичок.
Саме тому щиро раджу подію, на якій ви дізнаєтеся трошки більше, а саме
DevOps: Від Кодування до Хмари — безкоштовний мітап від Sigma Software University.
📅 3 червня, 18:30
🌐 Онлайн
🎯 У програмі: Linux, Git, Docker, AWS, CI/CD — і головне, практичний кейс, де все це працює разом.
Цей мітап буде корисним для тих, хто хоче бачити свою роботу системніше, а особливо — мідлам, які прагнуть стати синьйорами, а не просто записати в резюме черговий фреймворк.
.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤17🔥9
Свою першу справжню робочу таску я памʼятатиму, певно, усе життя. В одній точці часу-простору зійшлися з однієї сторони моя абсолютна недосвідченість та самовпевненість, а з іншої — якась просто непомірна задача, поставлена тімлідом, який виявився за сумісництвом моїм бувшим однокурсником.
Це був далекий 2011 рік, iPad видавався інопланетною технологією, а тач-інтерфейс я вперше в житті побачив за два дні до першого робочого дня. На співбесіді. І моя перша в житті таска була… була моя перша в житті таска…
Моїм повним фіаско. Дивіться самі — мені треба було зробити:
— Пінч-зум! (це коли ви два пальці то докупи, то врізнобіч робите)
— Під Safari! (очевидно, але я його бачив вперше в житті)
— На айпаді! (з віддаленим дебагом і нині справи не дуже, а тоді й поготів)
— …і фінальний акорд — на jQuery!
Очевидно, що я не те, що не впорався із задачею, я за повні робочі 8 годин (сам в шоці, що колись прямо по табелю працював) встиг знаєте, що зробить? Ніколи не здогадаєтесь.
За 8 годин я зміг отримати координати тапа, тобто куди пальцем в екран тикнуто. І так, лише для одного. Задачу було епічно й з тріском провалено. І її у мене, очевидно, забрали. Я, до речі, не памʼятаю, чи вона взагалі колись була доведена до кінця, бо вже дуже скоро ми відмовилися від jQuery на користь Zepto, а за тим швидко прийшов наш власний фреймворк.
Так от. Який я урок з цього виніс? Згадуючи ті часи, я тепер чітко розумію — ні-я-ко-го. Бо я був самовпевнений впертюх, який в жодному разі не піде й не запитається когось більш досвідченого, і буде самотньо посеред повного кабінету людей намарно намагатися досягти хоч якогось результату. І ще довго наступав на величезні граблі, зроблені з переоцінки моїх власних можливостей.
Ця задача запамʼяталася мені з багатьох причин. Не все варто зараз розбирати в деталях, але одну річ я засвоїв точно — іноді ти просто не справляєшся. І це нормально. Тут головне зробити правильні висновки і перетворити "невдачу" на поживний ґрунт для особистого професійного росту.
Не будьте як я у 2011-му: впертим, мовчазним та переконаним, що зобовʼязаний усе знати наперед. Будьте як ви у 2025-му — жваві, допитливі, та іноді трооошечки набридливі ;)
✅ @babichdev
***
Більше гривень — більше подарунків! Збір на РЕБ для 109 ОГШБ 10 ОГШБр «Едельвейс» триває, і ми впритул наблизились до другої мети в 50 000 грн! Кожні 50 грн — шанс виграти подарунок і допомогти ЗСУ.
Це був далекий 2011 рік, iPad видавався інопланетною технологією, а тач-інтерфейс я вперше в житті побачив за два дні до першого робочого дня. На співбесіді. І моя перша в житті таска була… була моя перша в житті таска…
Моїм повним фіаско. Дивіться самі — мені треба було зробити:
— Пінч-зум! (це коли ви два пальці то докупи, то врізнобіч робите)
— Під Safari! (очевидно, але я його бачив вперше в житті)
— На айпаді! (з віддаленим дебагом і нині справи не дуже, а тоді й поготів)
— …і фінальний акорд — на jQuery!
Очевидно, що я не те, що не впорався із задачею, я за повні робочі 8 годин (сам в шоці, що колись прямо по табелю працював) встиг знаєте, що зробить? Ніколи не здогадаєтесь.
За 8 годин я зміг отримати координати тапа, тобто куди пальцем в екран тикнуто. І так, лише для одного. Задачу було епічно й з тріском провалено. І її у мене, очевидно, забрали. Я, до речі, не памʼятаю, чи вона взагалі колись була доведена до кінця, бо вже дуже скоро ми відмовилися від jQuery на користь Zepto, а за тим швидко прийшов наш власний фреймворк.
Так от. Який я урок з цього виніс? Згадуючи ті часи, я тепер чітко розумію — ні-я-ко-го. Бо я був самовпевнений впертюх, який в жодному разі не піде й не запитається когось більш досвідченого, і буде самотньо посеред повного кабінету людей намарно намагатися досягти хоч якогось результату. І ще довго наступав на величезні граблі, зроблені з переоцінки моїх власних можливостей.
Ця задача запамʼяталася мені з багатьох причин. Не все варто зараз розбирати в деталях, але одну річ я засвоїв точно — іноді ти просто не справляєшся. І це нормально. Тут головне зробити правильні висновки і перетворити "невдачу" на поживний ґрунт для особистого професійного росту.
Не будьте як я у 2011-му: впертим, мовчазним та переконаним, що зобовʼязаний усе знати наперед. Будьте як ви у 2025-му — жваві, допитливі, та іноді трооошечки набридливі ;)
***
Більше гривень — більше подарунків! Збір на РЕБ для 109 ОГШБ 10 ОГШБр «Едельвейс» триває, і ми впритул наблизились до другої мети в 50 000 грн! Кожні 50 грн — шанс виграти подарунок і допомогти ЗСУ.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤78🔥11
Дивовижний світ веброзробки
#партнерський_допис Я на 100% впевнений, що серед вас немає нікого, хто бодай раз не робив git push (чули ви про про нього то точно), після якого щось там крутиться, скрипить, зеленіє, червоніє, падає, встає — і от ваш код уже в “проді”, де тисячі користувачів…
Вітаю, колеги! Сьогодні допис буде тільки один, і він буде не про веброзробку.
Я хочу нагадати вам, що досі триває наш з вами збір для 109 ОГШБ 10 ОГШБр "Едельвейс". Потрібно зібрати 100 000 гривень для дооплати засобу радіоелектронної боротьби.
Миз вами вже майже подолали половину збору, тож треба трохи піднатиснути і довести його до кінця! Якщо кожен з вас закине бодай по 50 гривень, ми закриємо цей збір за мить!
Нагадую, що кожні ваші 50 гривень, задоначені на збір — це додатковий шанс виграти один з чудових подарунків:
🎁 Пазл GoodLoot "Witcher: Griffin Fight"
Подарунок від мене особисто
🎯 Мета: 20 000 грн (розіграно, чекаю на підтвердження)
🎁 Клавіатура R-Go Compact Break
Від друзів з ERGO PLACE
🎯 Мета: 50 000 грн
🎁 LEGO Dune Atreides Royal Ornithopter
Від української продуктової IT-компанії Brainstack
🎯 Мета: 100 000 грн
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Дякую усім, хто долучається! І памʼятайте кожна гривня важлива.
Гарного та натхненного вам усім дня!
Я хочу нагадати вам, що досі триває наш з вами збір для 109 ОГШБ 10 ОГШБр "Едельвейс". Потрібно зібрати 100 000 гривень для дооплати засобу радіоелектронної боротьби.
Миз вами вже майже подолали половину збору, тож треба трохи піднатиснути і довести його до кінця! Якщо кожен з вас закине бодай по 50 гривень, ми закриємо цей збір за мить!
Нагадую, що кожні ваші 50 гривень, задоначені на збір — це додатковий шанс виграти один з чудових подарунків:
🎁 Пазл GoodLoot "Witcher: Griffin Fight"
Подарунок від мене особисто
🎯 Мета: 20 000 грн (розіграно, чекаю на підтвердження)
🎁 Клавіатура R-Go Compact Break
Від друзів з ERGO PLACE
🎯 Мета: 50 000 грн
🎁 LEGO Dune Atreides Royal Ornithopter
Від української продуктової IT-компанії Brainstack
🎯 Мета: 100 000 грн
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Дякую усім, хто долучається! І памʼятайте кожна гривня важлива.
Гарного та натхненного вам усім дня!
❤15🔥4
DOCTYPE писати не треба!
Саме так я вважав досить тривалий час: ніби ж HTML5 і так тепер скрізь за замовчанням, бравзери розумні, самі розберуться, хіба ні?
Я не міг помилятися більше.
DOCTYPE — це особлива декларація, яка пояснює бравзеру, за яким саме стандартом треба обробляти конкретний документ. Сьогодні він має виглядати як
Раніше ж ця декларація мала наступний вигляд:
І вказувала який конкретно стандарт використовується і, мало того, містила пряме посилання на DTD, Document Type Definiton, набір інструкцій для бравзера, які описують як обробляти ті чи інши теги. Ці посилання активні й зараз, і ви можете почитати, що ж там такого пише.
Так от, а що ж станеться, якщо не вказати DOCTYPE?
Тоді буде увімкнено quirks mode: режим рендерингу, в якому імітується поведінка старих бравзерів для забезпечення сумісності з застарілими веб-сторінками. Це означає, що бравзер може відображати сторінку з помилками чи некоректно інтерпретувати сучасний CSS.
Це може призвести до багатьох "цікавих" наслідків, серед яких можлива неправильна обробка семантичних елементів, що може суттєво впливати на доступність, чи застосовуватись якісь CSS-хаки з доісторичних часів, через що непередбачувано попливуть ваші стилі, і ще всілякі інші сюрпризи.
І от саме тому вказувати DOCTYPE в документі зараз важливо, як ніколи, якщо ми хочемо, аби бравзер правильно обробляв його, ми могли використовувати найсучасніші можливості HTML та CSS, і нам не боліла голова через кросбравзерність (вірніше її відсутність). Якщо коротко — DOCTYPE це єдиний спосіб гарантувати, що бравзер працює в сучасному стандартному режимі, а не перетворюється на симулятор Internet Explorer 5.
Спробуйте відкрити свою стару верстку без <!DOCTYPE html> — і розкажіть в коментарях, наскільки все поїхало. Або не поїхало 😉
MDN: Understanding quirks and standards modes
@babichdev
***
Збір на РЕБ для 109 ОГШБ 10 ОГШБр «Едельвейс» триває, і ми вже перетнули позначку в 50 000 грн! Нагадую, кожні 50 грн — шанс виграти подарунок і допомогти ЗСУ.
Саме так я вважав досить тривалий час: ніби ж HTML5 і так тепер скрізь за замовчанням, бравзери розумні, самі розберуться, хіба ні?
Я не міг помилятися більше.
DOCTYPE — це особлива декларація, яка пояснює бравзеру, за яким саме стандартом треба обробляти конкретний документ. Сьогодні він має виглядати як
<!DOCTYPE html>, і цього цілком достатньо, аби бравзер знав — обробляти html треба за останнім писком моди.Раніше ж ця декларація мала наступний вигляд:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
І вказувала який конкретно стандарт використовується і, мало того, містила пряме посилання на DTD, Document Type Definiton, набір інструкцій для бравзера, які описують як обробляти ті чи інши теги. Ці посилання активні й зараз, і ви можете почитати, що ж там такого пише.
Так от, а що ж станеться, якщо не вказати DOCTYPE?
Тоді буде увімкнено quirks mode: режим рендерингу, в якому імітується поведінка старих бравзерів для забезпечення сумісності з застарілими веб-сторінками. Це означає, що бравзер може відображати сторінку з помилками чи некоректно інтерпретувати сучасний CSS.
А от якщо ти поставиш вподобайку цьому допису, то ніякий quirks mode твою верстку не зламає.
Це може призвести до багатьох "цікавих" наслідків, серед яких можлива неправильна обробка семантичних елементів, що може суттєво впливати на доступність, чи застосовуватись якісь CSS-хаки з доісторичних часів, через що непередбачувано попливуть ваші стилі, і ще всілякі інші сюрпризи.
І от саме тому вказувати DOCTYPE в документі зараз важливо, як ніколи, якщо ми хочемо, аби бравзер правильно обробляв його, ми могли використовувати найсучасніші можливості HTML та CSS, і нам не боліла голова через кросбравзерність (вірніше її відсутність). Якщо коротко — DOCTYPE це єдиний спосіб гарантувати, що бравзер працює в сучасному стандартному режимі, а не перетворюється на симулятор Internet Explorer 5.
Спробуйте відкрити свою стару верстку без <!DOCTYPE html> — і розкажіть в коментарях, наскільки все поїхало. Або не поїхало 😉
MDN: Understanding quirks and standards modes
@babichdev
***
Збір на РЕБ для 109 ОГШБ 10 ОГШБр «Едельвейс» триває, і ми вже перетнули позначку в 50 000 грн! Нагадую, кожні 50 грн — шанс виграти подарунок і допомогти ЗСУ.
❤71🔥21👏5
#ДонатНаРЕБ
Друзі, ми перетнули позначку в 50 000 гривень в нашому зборі для 109 ОГШБ 10 ОГШБр "Едельвейс", а це значить, що клавіатура R-Go Compact Break від моїх друзів з ERGO PLACE знайшла свого власника!
Тепер останній ривок і фінальна мета в 100 000 гривень, після якої я розіграю 🎁 LEGO Dune Atreides Royal Ornithopter від української продуктової IT-компанії Brainstack!
Нагадую, що кожні 50 гривень вашого донату — це додатковий шанс стати власником цього чудового подарунку!
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Дякую усім, хто долучається! І памʼятайте — кожна гривня важлива.
Друзі, ми перетнули позначку в 50 000 гривень в нашому зборі для 109 ОГШБ 10 ОГШБр "Едельвейс", а це значить, що клавіатура R-Go Compact Break від моїх друзів з ERGO PLACE знайшла свого власника!
Тепер останній ривок і фінальна мета в 100 000 гривень, після якої я розіграю 🎁 LEGO Dune Atreides Royal Ornithopter від української продуктової IT-компанії Brainstack!
Нагадую, що кожні 50 гривень вашого донату — це додатковий шанс стати власником цього чудового подарунку!
🔗 Банка mono:
https://send.monobank.ua/jar/9XkNDTzHAZ
💳 Картка mono:
4441111124390562
Дякую усім, хто долучається! І памʼятайте — кожна гривня важлива.
🔥8❤1