Что такое декларативность и императивность?
Императивный подход написания кода фокусируется на том, КАК именно должна быть выполнена задача. В императивном стиле вы указываете шаг за шагом, что должно происходить, ничего не скрывая, например:
В этом примере мы явно указываем, как именно нужно создать список: создаем элементы, задаем им текст и добавляем в список.
Декларативный же подход фокусируется на том, ЧТО нужно сделать. В декларативном стиле вы описываете результат, который хотите получить, а не процесс его достижения, например:
В этом примере с использованием React мы описываем, что хотим увидеть: список элементов. Мы не указываем, как именно React должен создать и добавить эти элементы, мы просто описываем структуру, которую хотим получить
Императивный стиль дает вам полный контроль над процессом выполнения, что может быть полезно для сложных алгоритмов и точной настройки.
Декларативный стиль, как правило, делает код более читаемым и легким для понимания, так как вы описываете только конечный результат. Также декларативный код часто легче поддерживать и изменять, так как он фокусируется на описании желаемого состояния, а не на пошаговом выполнении.
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript #principles
Императивный подход написания кода фокусируется на том, КАК именно должна быть выполнена задача. В императивном стиле вы указываете шаг за шагом, что должно происходить, ничего не скрывая, например:
// Императивный способ создания списка из элементов массива
const items = [1, 2, 3, 4, 5];
const ul = document.createElement('ul');
for (let i = 0; i < items.length; i++) {
const li = document.createElement('li');
li.textContent = items[i];
ul.appendChild(li);
}
document.body.appendChild(ul);
В этом примере мы явно указываем, как именно нужно создать список: создаем элементы, задаем им текст и добавляем в список.
Декларативный же подход фокусируется на том, ЧТО нужно сделать. В декларативном стиле вы описываете результат, который хотите получить, а не процесс его достижения, например:
import React from 'react';
import ReactDOM from 'react-dom';
const items = [1, 2, 3, 4, 5];
const App = () => (
<ul>
{items.map(item => (
<li key={item}>{item}</li>
))}
</ul>
);
ReactDOM.render(<App />, document.getElementById('root'));
В этом примере с использованием React мы описываем, что хотим увидеть: список элементов. Мы не указываем, как именно React должен создать и добавить эти элементы, мы просто описываем структуру, которую хотим получить
Императивный стиль дает вам полный контроль над процессом выполнения, что может быть полезно для сложных алгоритмов и точной настройки.
Декларативный стиль, как правило, делает код более читаемым и легким для понимания, так как вы описываете только конечный результат. Также декларативный код часто легче поддерживать и изменять, так как он фокусируется на описании желаемого состояния, а не на пошаговом выполнении.
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript #principles
❤25👍13🔥6🐳2
Остановка распространения событий: event.stopPropogation и event.stopImmediatePropagation()
Итак, эти методы используются для управления событиями в JavaScript. Сначала разберём каждый из них по отдельности:
🟢 event.stopPropagation()
Этот метод предотвращает дальнейшее распространение события в фазе захвата или всплытия. Это значит, что событие сработает только на
Так как мы используем
🟢 event.stopImmediatePropagation()
Этот метод не только предотвращает дальнейшее распространение события к родителям, но и останавливает выполнение других обработчиков событий на том же элементе. Рассмотрим пример:
При клике на элемент, в консоли мы увидим только лишь
В этом посте в качестве эксперимента сделал блок "коротко о главном", чтобы проще было усваивать материал и не приходилось читать очень длинные посты, если тема вам оказалась неинтересна. Накидайте 🔥 если этот блок — пушка-гонка, а я постараюсь добавлять его чаще
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
Итак, эти методы используются для управления событиями в JavaScript. Сначала разберём каждый из них по отдельности:
Этот метод предотвращает дальнейшее распространение события в фазе захвата или всплытия. Это значит, что событие сработает только на
event.target
, то есть на самом элементе, но не на всех его родителях, как это сделано по умолчанию. Рассмотрим код:document.getElementById('child').addEventListener('click', event => {
event.stopPropagation();
console.log('Ребёнок');
});
document.getElementById('parent').addEventListener('click', () => {
console.log('Родитель');
});
Так как мы используем
event.stopPropogation()
, в консоли мы увидим только Ребёнок
. Без использования этого метода, мы увидим вывод: Ребёнок
, Родитель
Этот метод не только предотвращает дальнейшее распространение события к родителям, но и останавливает выполнение других обработчиков событий на том же элементе. Рассмотрим пример:
const element = document.getElementById('child')
element.addEventListener('click', event => {
event.stopImmediatePropagation();
console.log('Первый обработчик нажатия');
});
element.addEventListener('click', () => {
console.log('Второй обработчик нажатия');
});
При клике на элемент, в консоли мы увидим только лишь
Первый обработчик нажатия
. Второй обработчик не выполнится, потому что event.stopImmediatePropagation()
остановил выполнение других обработчиков на этом элементеКоротко о главном:
- event.stopPropagation() используется для остановки распространения события на родительские элементы
- event.stopImmediatePropagation() используется для полной остановки события, включая другие обработчики на текущем элементе
В этом посте в качестве эксперимента сделал блок "коротко о главном", чтобы проще было усваивать материал и не приходилось читать очень длинные посты, если тема вам оказалась неинтересна. Накидайте 🔥 если этот блок — пушка-гонка, а я постараюсь добавлять его чаще
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥42👍11❤2🐳2
JavaScript не в браузере: NodeJS, Deno и Bun
Начать стоит с того, что JavaScript может выполняться далеко не только в браузере. Для этого есть такая штука, как рантайм — это среда выполнения, которая обеспечивает все необходимое для выполнения JavaScript кода: движок языка, API среды и т.д.
Рантаймов несчётном множество, как и всего в мире JS, но в этом поговорим о самых интересных: NodeJS, Deno и Bun
👩💻 NodeJS — это рантайм JavaScript, построенный на движке V8 от Google Chrome. Он позволяет выполнять JavaScript-код на сервере. По сути, это почти то же самое, что и выполнять код в браузере, за тем лишь исключением, что NodeJS предоставляет API по работе с файлами, операционной системой, среду исполнения тестов и кучу всего ещё
— NodeJS сейчас — это основной рантайм для всех серверных решений на JavaScript и TypeScript
—
👩💻 Deno — более новый, чем NodeJS, рантайм, от создателя NodeJS. Deno разработан для того, чтобы устранить некоторые недостатки и ограничения ноды, улучшить безопасность и лучшей поддержкой TypeScript. В целом, всё так и есть, только лично мне субъективно кажется, что Deno почти никто не использует(
👩💻 Bun — самый новый из этой тройки инструмент, который разработан для того, чтобы быть самым быстрым и легким в использовании, предлагая ряд улучшений по сравнению с другими инструментами. Bun быстрее запускает код, сильно лучше работает с асинхронными запросами, быстрее устанавливает зависимости... Но ему слишком мало лет, чтобы активно тащить его в прод — пока рановато
Лично я ставлю на то, что доминирующего рантайма пока что не будет, получится зоопарк, так как всем просто не угодить
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #typescript #useful
Начать стоит с того, что JavaScript может выполняться далеко не только в браузере. Для этого есть такая штука, как рантайм — это среда выполнения, которая обеспечивает все необходимое для выполнения JavaScript кода: движок языка, API среды и т.д.
Рантаймов несчётном множество, как и всего в мире JS, но в этом поговорим о самых интересных: NodeJS, Deno и Bun
— NodeJS сейчас — это основной рантайм для всех серверных решений на JavaScript и TypeScript
—
npm
(Node Package Manager) — это тоже про нодуКраткий итог:
— NodeJS - это зрелая платформа с обширной экосистемой и большим сообществом
— Deno - альтернатива NodeJS с улучшенной безопасностью, поддержкой TypeScript и другими плюшками
— Bun - новая и перспективная платформа с упором на скорость и интеграцию различных инструментов
Лично я ставлю на то, что доминирующего рантайма пока что не будет, получится зоопарк, так как всем просто не угодить
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #typescript #useful
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥22👍12❤11🐳1
Виды операторов в JavaScript
Операторы в языке (почти во всех языках, кстати), можно строго разделить на три категории:
1. Унарные операторы
Работают с одним операндом — то есть применяются только к одной переменной. Это, например, такие операторы, как
2. Бинарные операторы
Бинарные операторы работают с двумя операндами. Это самые распространенные операторы, включающие арифметические, логические, сравнительные и присваивающие операции
3. Тернарный оператор
Тернарный оператор — единственный оператор, который работает с тремя операндами и является сокращенной формой конструкции
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
Операторы в языке (почти во всех языках, кстати), можно строго разделить на три категории:
1. Унарные операторы
Работают с одним операндом — то есть применяются только к одной переменной. Это, например, такие операторы, как
i++
или --i
, смены знака -i
или отрицания !isTrue
let a = 5;
a++; // теперь a равно 6
let b = -a; // теперь b равно -6
Операнд — это элемент данных, над которым выполняется операция. В выражении i++ переменная i будет операндом, а ++ — оператором
2. Бинарные операторы
Бинарные операторы работают с двумя операндами. Это самые распространенные операторы, включающие арифметические, логические, сравнительные и присваивающие операции
const x = 10;
const y = 20;
const sum = x + y; // (+) - арифметический оператор
const isEqual = x == y; // (==) - сравнительный оператор
3. Тернарный оператор
Тернарный оператор — единственный оператор, который работает с тремя операндами и является сокращенной формой конструкции
if-else
. Он часто используется для кратких условийconst age = 31
const canKupitPivo = age >= 18 ? true : false
Краткий итог:
Операторы бывают трёх видов — унарные, бинарные и тернарные. Работают они с одним, двумя и тремя операндами соответственно
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
👍25❤9🔥5🐳1
Как определить с какого устройства открыт сайт
Самым простым способом является анализ строки User-Agent’a — это специальный заголовок, который передаётся браузером устройства вместе с любым запросом.
Сразу рассмотрим на примере:
Из этой строки можно достать информацию об устройстве пользователя, его операционной системе и браузере.
Чтобы проанализировать строку, можно воспользоваться либо готовыми библиотеками, либо написать примерно такой код:
Выше достаточно упрощённая версия кода, просто чтобы передать основную идею.
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
Самым простым способом является анализ строки User-Agent’a — это специальный заголовок, который передаётся браузером устройства вместе с любым запросом.
Сразу рассмотрим на примере:
Запрос с айфона из Safari:
Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1
Запрос с комьютера из Google Chrome:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
Из этой строки можно достать информацию об устройстве пользователя, его операционной системе и браузере.
Чтобы проанализировать строку, можно воспользоваться либо готовыми библиотеками, либо написать примерно такой код:
const isMobile = () => /Mobi|Android/i.test(navigator.userAgent)
if (isMobile()) {
console.log("Мобильное устройство");
} else {
console.log("Десктопное устройство");
}
Выше достаточно упрощённая версия кода, просто чтобы передать основную идею.
Пригодиться это может в нескольких кейсах:
— для изменения вёрстки под особенности устройства
— для сбора аналитики
— подключение и использование специфичных API (геолокация, сенсорные жесты, вибрация и пр.)
— ну и точно что-то ещё, о чём я мог забыть
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript
👍25🔥6❤5🐳2
Что такое Callback Hell и как с ним бороться?
Частый вопрос с собеса, особенно если идти куда-то повыше стажёра.
Callback Hell — это ситуация в асинхронном программировании, когда вложенные друг в друга функции обратного вызова (он же callback) образуют "лесенку", что делает код трудным для чтения и сопровождения.
Как с этим можно бороться?
Конечно же промисы и async/await синтаксис:
Промисы позволяют писать асинхронный код более линейно и читаемо благодаря цепочке вызовов (chaining):
А async/await — это более современный синтаксис над промисами, который так же позволяет развернуть вложенные колбеки в плоский код:
И о Promise, и о async/await у меня уже есть более подробные посты
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript #patterns #data
Частый вопрос с собеса, особенно если идти куда-то повыше стажёра.
Callback Hell — это ситуация в асинхронном программировании, когда вложенные друг в друга функции обратного вызова (он же callback) образуют "лесенку", что делает код трудным для чтения и сопровождения.
doSomething(function(result) {
doSomethingElse(result, function(newResult) {
doAnotherThing(newResult, function(finalResult) {
doSomethingMore(finalResult, function(lastResult) {
console.log(lastResult);
});
});
});
});
Как с этим можно бороться?
Конечно же промисы и async/await синтаксис:
Промисы позволяют писать асинхронный код более линейно и читаемо благодаря цепочке вызовов (chaining):
doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doAnotherThing(newResult))
.then(finalResult => console.log(finalResult))
.catch(error => console.error(error));
А async/await — это более современный синтаксис над промисами, который так же позволяет развернуть вложенные колбеки в плоский код:
async function process() {
try {
const result = await doSomething();
const newResult = await doSomethingElse(result);
const finalResult = await doAnotherThing(newResult);
console.log(finalResult);
} catch (error) {
console.error(error);
}
}
process();
И о Promise, и о async/await у меня уже есть более подробные посты
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #code #javascript #patterns #data
🔥18❤9👍9🐳3
Как отменить уже отправленный HTTP запрос?
Для отмены уже отправленного запроса нам пригодится встроенный в JavsScript объект —
Этот объект позволяет отменять уже запущенные асинхронные операции,
Нужно это много где, я приведу самый очевидный пример с реактом:
Представим, что пользователь открывает страницу. На странице в
Использование🌚
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code #data
Для отмены уже отправленного запроса нам пригодится встроенный в JavsScript объект —
AbortController
Этот объект позволяет отменять уже запущенные асинхронные операции,
fetch
в том числеconst controller = new AbortController()
// отправляем запрос
fetch('https://.../', { signal: controller.signal })
// отменяем его
controller.abort()
Нужно это много где, я приведу самый очевидный пример с реактом:
Представим, что пользователь открывает страницу. На странице в
useEffect
идёт запрос к API, но пользователь, не дожидаясь ответа от сервера, переходит на другую страницу. Запрос есть, трафик занят, есть риск нарушения жизненного цикла компонента, а результаты этого запроса уже и вовсе не нужны. Вот так это решается:useEffect(() => {
const controller = new AbortController()
// делаем запрос на маунт компонента
fetch('https://.../', { signal: controller.signal })
// отменяем запрос на анмаунт компонента
return () => controller.abort()
}, [])
Использование
AbortController'a
помогает избежать потенциальных утечек памяти и гарантирует, что запросы не будут выполняться после того, как компонент был размонтирован. Полезно это при любых запросах, так что можно смело сделать свой хук обёртку. Или просто использовать @tanstack/react-query
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code #data
Please open Telegram to view this post
VIEW IN TELEGRAM
👍32❤11🔥3🐳2🤯1🤩1
Разница между CommonJS и ES Modules
Если по простому, то CommonJS и ES (ECMAScript) Modules — это два способа импорта и экспорта чего либо из файлов в JavaScript
CommonJS — относительно старый API, который был разработан для NodeJS. Выглядит он следующим образом:
ES Modules — это подход, который в язык принес ECMAScript 2015 (ES6). Он задумывался как замена устаревшему CommonJS и выглядит так:
ИМХО, в современной разработке от CommonJS можно отказаться как от рудимента. Я стараюсь использовать модули по максимуму
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code
Если по простому, то CommonJS и ES (ECMAScript) Modules — это два способа импорта и экспорта чего либо из файлов в JavaScript
CommonJS — относительно старый API, который был разработан для NodeJS. Выглядит он следующим образом:
// Экспорт
module.exports = function() {
console.log(...);
};
// Импорт
const module = require('./module');
module();
Особенностью CommonJS является синхронная загрузка модулей. Это означает, что когда один модуль требует другой модуль, выполнение кода приостанавливается до тех пор, пока требуемый модуль не будет загружен и выполнен
Для браузера, синхронная загрузка — крайне неудачный подход из-за блокировки интерфейса в момент загрузки. Поэтому в браузере использовать CommonJS — моветон, лучше использовать ES Modules
ES Modules — это подход, который в язык принес ECMAScript 2015 (ES6). Он задумывался как замена устаревшему CommonJS и выглядит так:
// Экспорт
export function foo() {
console.log(...)
}
// Импорт
import { foo } from './module.js';
foo();
ES Modules поддерживают асинхронную загрузку модулей и лучше умеют в статический анализ, что лучше как со стороны пользователя, так и разработчика.
Также ES Modules могут использоваться не только в браузере, а и в NodeJS, начиная аж с 12 версии. Как же давно это было🥲
ИМХО, в современной разработке от CommonJS можно отказаться как от рудимента. Я стараюсь использовать модули по максимуму
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code
👍30❤11🐳6🔥5
Что такое виртуализация?
Это крайне популярная техника оптимизации, которая позволяет эффективно управлять отображением большого количества элементов на странице. Особенно она полезна при отображении большого массива данных в списках, таблицах и прочих подобных элементах
Если объяснять на пальцах как это работает, то я бы сказал так:
Мы можем представить, что хотим послушать музыку. Открываем что-то типа Тындыкс.Музыки и видим 10.000 разных треков — это 10.000 строк огромного списка
Так вот, зачем отображать все 10.000 сразу, если на экране в лучшем случае поместиться треков 20-30? Давайте рисовать только первые, например, 50 треков, а дальше следить за тем что видит пользователь — за его скроллом. Если пользователь прокрутит ещё на 20 строк вниз, то мы нарисуем следующие 20 строк, а первые 20 удалим из вёрстки
Под коробкой все виртуализаторы как раз этим и занимаются:
1. Определяют какие элементы видны пользователю сейчас
2. Определяют сколько элементов скрыто над и под окном просмотра
Чаще всего это реализуют через события
Виртуализация может пригодиться в огромном срезе приложений, поэтому очень советую с ней ознакомиться заранее, если вы ещё не успели
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code #react
Это крайне популярная техника оптимизации, которая позволяет эффективно управлять отображением большого количества элементов на странице. Особенно она полезна при отображении большого массива данных в списках, таблицах и прочих подобных элементах
Я очень рекомендую TanStack Virtual для этой задачи. Мне уже удалось применить его на нескольких проектах и никаких проблем он не вызывал
Если объяснять на пальцах как это работает, то я бы сказал так:
Мы можем представить, что хотим послушать музыку. Открываем что-то типа Тындыкс.Музыки и видим 10.000 разных треков — это 10.000 строк огромного списка
Так вот, зачем отображать все 10.000 сразу, если на экране в лучшем случае поместиться треков 20-30? Давайте рисовать только первые, например, 50 треков, а дальше следить за тем что видит пользователь — за его скроллом. Если пользователь прокрутит ещё на 20 строк вниз, то мы нарисуем следующие 20 строк, а первые 20 удалим из вёрстки
Под коробкой все виртуализаторы как раз этим и занимаются:
1. Определяют какие элементы видны пользователю сейчас
2. Определяют сколько элементов скрыто над и под окном просмотра
Чаще всего это реализуют через события
scroll
на контейнере или через IntersectionObserver
, подробности реализации для особо любопытных всегда доступны в сорсах библиотек (в TanStack Virtual можете начать с функции observeElementRect)Виртуализация может пригодиться в огромном срезе приложений, поэтому очень советую с ней ознакомиться заранее, если вы ещё не успели
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #theory #javascript #code #react
🐳26👍9❤5🔥4
Как менять состояние вкладки по интервалу
Полезная фича для демонстрации, например, уведомлений, которая может пригодиться на очень большом количестве сайтов
Для реализации нам необходимо создать состояния, между которыми мы хотим перемещаться:
Далее необходимо завести состояние, которое будет определять на каком этапе из списка состояний мы сейчас находимся. Это состояние можно будет менять через обычный интервал:
И в зависимости от текущего состояния изменяем параметры вкладки:
Очевидно, что в таком исполнении решение выглядит не очень красиво. Можно создать кастомный хук и вынести всю логику туда, например, или воспользоваться нативными контекстами. В общем, сделать из этого решения либу, которую можно будет легко перенести из проекта в проект
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #code #web #theory #javascript #react
Полезная фича для демонстрации, например, уведомлений, которая может пригодиться на очень большом количестве сайтов
Для реализации нам необходимо создать состояния, между которыми мы хотим перемещаться:
const states = [
{ title: "Мессенджер", icon: Favicon1 },
{ title: "Новое сообщение", icon: Favicon2 },
]
Далее необходимо завести состояние, которое будет определять на каком этапе из списка состояний мы сейчас находимся. Это состояние можно будет менять через обычный интервал:
const [stateIndex, setStateIndex] = useState(0);
// раз в секунду переходим на следующее состояние
useEffect(() => {
const intervalId = setInterval(() => {
setStateIndex((prevIndex) => (prevIndex + 1) % states.length);
}, 1000);
return () => clearInterval(intervalId);
}, []);
И в зависимости от текущего состояния изменяем параметры вкладки:
useEffect(() => {
const link = document.querySelector("link[rel~='icon']");
const title = document.querySelector("head title");
if (link) {
link.href = states[stateIndex].icon;
title.textContent = states[stateIndex].title;
}
}, [stateIndex]);
Очевидно, что в таком исполнении решение выглядит не очень красиво. Можно создать кастомный хук и вынести всю логику туда, например, или воспользоваться нативными контекстами. В общем, сделать из этого решения либу, которую можно будет легко перенести из проекта в проект
Спасибо за прочтение, это важно для меня ❤️
@prog_way_blog — чат — #code #web #theory #javascript #react
🐳22😐8👍5❤4🔥2