progway — программирование, IT
2.68K subscribers
25 photos
1 video
246 links
Чат: @prog_way_chat

Разборы вопросов и задач с собеседований, мысли, полезные материалы и просто вещи, что мне интересны из мира IT

Полезности и навигация в закрепе

По всем вопросам: @denisputnov
Download Telegram
Что такое декларативность и императивность?

Императивный подход написания кода фокусируется на том, КАК именно должна быть выполнена задача. В императивном стиле вы указываете шаг за шагом, что должно происходить, ничего не скрывая, например:

// Императивный способ создания списка из элементов массива
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.target, то есть на самом элементе, но не на всех его родителях, как это сделано по умолчанию. Рассмотрим код:
document.getElementById('child').addEventListener('click', event => {
event.stopPropagation();
console.log('Ребёнок');
});

document.getElementById('parent').addEventListener('click', () => {
console.log('Родитель');
});


Так как мы используем event.stopPropogation(), в консоли мы увидим только Ребёнок. Без использования этого метода, мы увидим вывод: Ребёнок, Родитель

🟢event.stopImmediatePropagation()

Этот метод не только предотвращает дальнейшее распространение события к родителям, но и останавливает выполнение других обработчиков событий на том же элементе. Рассмотрим пример:
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👍112🐳2
Виды операторов в 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
👍259🔥5🐳1
Как определить с какого устройства открыт сайт

Самым простым способом является анализ строки 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🔥65🐳2
Что такое Callback Hell и как с ним бороться?

Частый вопрос с собеса, особенно если идти куда-то повыше стажёра.

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
🔥189👍9🐳3
CSS для печати страниц

Несколько лет назад я делал пет-проект — конструктор резюме. Кейс был такой, что хотелось сразу же печатать созданное резюме при нажатии сочетания клавиш Ctrl+P в браузере. Но проблема в том, что помимо самого резюме на печать попадало не только само резюме, а все кнопки, поля и прочие элементы страницы для его настройки. Такие кейсы можно решать при помощи CSS медиазапроса @media print:

@media print {
/* стили для печати */
}


То есть во время печати мы можем скрыть все ненужные элементы:

@media print {
.navbar, .footer, .controls {
display: none;
}
}


Ну или ещё проще:

@media print {
.no-print {
display: none;
}
}


А сам класс .no-print проставлять на все скрываемые при печати элементы.

Также есть ещё специальные CSS свойства печати, например, break-inside, которое дополнительно настраивает можно ли переместить блок со страницы на страницу при печати, что особенно актуально для целостных блоков типа “контакты” в резюме. Если указать break-inside: avoid, то такой элемент не сможет быть расположен на двух страницах сразу, а перенесётся весь, если для него не хватает места.

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

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#theory #code #web #useful
👍34🔥84🐳1
Как отменить уже отправленный HTTP запрос?

Для отмены уже отправленного запроса нам пригодится встроенный в 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
👍3211🔥3🐳2🤯1🤩1
Разница между CommonJS и ES Modules

Если по простому, то 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
👍3011🐳6🔥5
Как убрать стили на под-дереве — мини-задача с реального проекта

Недавно был следующий кейс: в долгоживущий проект интегрировали tailwind со своими обнуляющими стилями. Эти стили очень нужны проекту, но на одной из страничек есть Rich-текст, приходящий с апишки, который, к сожалению, частично завязан на браузерные стили, и, после добавления обнуляющих стилей tailwind, весь поплыл

Обнуляющие стили — это когда все заголовки, списки и прочие HTML теги сбрасывают свои стандартные браузерные стили, чтобы тег нёс за собой только семантику


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

Обнулить все стили на под-дереве можно с помощью CSS свойства all. Выглядеть это может так:
.tailwind-reset-styles * {
all: revert;
}


Свойство all может сбросить все CSS свойства до их начального или унаследованного значения, что конкретно в моём случае полностью решало все проблемы

Далее полученный класс .tailwind-reset-styles вешаем на родительский тег, все под-дерево которого уже будет со сброшенными ненаследуемыми стилями. Это, наверное, самое элегантное и быстрое решение, что можно придумать в этой ситуации

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

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#theory #web #code
👍296🔥5🐳5
Что такое SWC и немного о Rust

SWC — это аббревиатура, которая всё чаще появляется в мире фронтенда. Расшифровывается это как Speedy Web Compiler и полностью оправдывает своё название, ведь SWC — это ультрабыстрый компилятор и пакетный обработчик, написанный на Rust. Он предназначен для преобразования современного JavaScript и TypeScript кода в код, который будет поддерживаться большинством браузеров. Возможно это во многом из-за полифилов, о которых я писал в этом посте

Если ещё проще, то SWC выполняет все функции Babel, только делает это в более чем 20 раз быстрее на одном ядре, и более чем в 70 раз быстрее на 4 ядрах.

Снова Rust всех победил 🤷‍♂️🤷‍♂️🤷‍♂️


Уже сейчас SWC используется в продуктах Vercel (в Next.js и Turbopack в том числе), Tencent, Shopify и других компаний, а также ложится в основу Vite начиная ещё с 4 версии (сейчас 5), так что с нами он плюс минус на долго

Да и больше про SWC сказать обзорно особо нечего. Мне во всём этом очень занимательно наблюдать за тем, какой огромный фокус на скорость появляется в фронтенде. Rust постепенно захватывает тулинг фронтенда: сборщики, компиляторы, линтеры и так далее — уже почти в каждой части тулинга есть решение на Rust и это, очевидно, не просто так

Ну и также не стоит забывать, что Rust уже давно имеет полную поддержку WebAssembly и является одним из основных языков этой технологии. Лично мне очень интересно понаблюдать, куда это всё приведёт. Накидывайте китов , сделаю отдельный пост по WebAssembly

Спасибо за прочтение, это важно для меня ❤️

@prog_way_blogчат#theory #web #code
Please open Telegram to view this post
VIEW IN TELEGRAM
🐳397👍3🔥2