<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>HackerX</title>
    <link>https://hackerx.ru/</link>
    <description>Recent content on HackerX</description>
    <generator>Hugo</generator>
    <language>ru-RU</language>
    <lastBuildDate>Fri, 17 Jul 2026 00:00:00 +0300</lastBuildDate>
    <atom:link href="https://hackerx.ru/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Buffer в Node.js: работа с бинарными данными</title>
      <link>https://hackerx.ru/node-buffer/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-buffer/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Buffer хранит сырые байты&lt;/strong&gt; — файлы, картинки, сетевые пакеты, то, что нельзя представить строкой.&lt;/li&gt;&#xA;&lt;li&gt;Он наследник &lt;code&gt;Uint8Array&lt;/code&gt;: ведёт себя как массив байтов, но умеет кодировки и работу с числами.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Buffer.alloc&lt;/code&gt; обнуляет память, &lt;code&gt;Buffer.allocUnsafe&lt;/code&gt; — нет.&lt;/strong&gt; По умолчанию &lt;code&gt;alloc&lt;/code&gt;: &lt;code&gt;allocUnsafe&lt;/code&gt; может отдать наружу чужие данные.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Длина в байтах ≠ длина строки:&lt;/strong&gt; кириллица в UTF-8 — два байта на символ, эмодзи — до четырёх.&lt;/li&gt;&#xA;&lt;li&gt;Склеивать буферы только через &lt;code&gt;Buffer.concat&lt;/code&gt;, а не через строку — иначе многобайтовый символ порвётся.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Cluster в Node.js: используем все ядра процессора</title>
      <link>https://hackerx.ru/node-cluster/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-cluster/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Один процесс Node = одно ядро.&lt;/strong&gt; Cluster запускает несколько процессов-воркеров и распределяет между ними запросы.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Число воркеров&lt;/strong&gt; — обычно по числу ядер (&lt;code&gt;os.cpus().length&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Воркеры не делят память&lt;/strong&gt; — каждый отдельный процесс; общее состояние выносят в &lt;a href=&#34;https://hackerx.ru/redis-%D0%B8-node-js/&#34;&gt;Redis&lt;/a&gt; или БД.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Отличие от &lt;a href=&#34;https://hackerx.ru/node-worker-threads/&#34;&gt;worker threads&lt;/a&gt;:&lt;/strong&gt; cluster — процессы для запросов, threads — потоки для вычислений.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;В продакшене чаще PM2&lt;/strong&gt; — сам поднимает и перезапускает воркеры.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Главный процесс распределяет входящие запросы между несколькими воркерами-процессами, каждый на своём ядре процессора&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;NODE.JS · CLUSTER&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;34&#34; y=&#34;176&#34; width=&#34;130&#34; height=&#34;80&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;34&#34; y=&#34;176&#34; width=&#34;130&#34; height=&#34;80&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;99&#34; y=&#34;210&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;запросы&lt;/text&gt;&#xA;  &lt;text x=&#34;99&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;трафик&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;214&#34; y=&#34;166&#34; width=&#34;180&#34; height=&#34;100&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;214&#34; y=&#34;166&#34; width=&#34;180&#34; height=&#34;100&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;304&#34; y=&#34;205&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Primary&lt;/text&gt;&#xA;  &lt;text x=&#34;304&#34; y=&#34;232&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;распределяет&lt;/text&gt;&#xA;&#xA;  &lt;path d=&#34;M 166 216 L 210 216&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M210,216 l-13,-6 l0,12 z&#34;/&gt;&#xA;&#xA;  &#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;520&#34; y=&#34;86&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;520&#34; y=&#34;86&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;560&#34; y=&#34;126&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;W1&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;115&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;CPU core 1&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;136&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;:3000&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;520&#34; y=&#34;172&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;520&#34; y=&#34;172&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;560&#34; y=&#34;212&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;W2&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;201&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;CPU core 2&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;222&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;:3000&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;520&#34; y=&#34;258&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;520&#34; y=&#34;258&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;560&#34; y=&#34;298&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;W3&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;287&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;CPU core 3&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;308&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;:3000&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;520&#34; y=&#34;344&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;520&#34; y=&#34;344&#34; width=&#34;240&#34; height=&#34;66&#34; rx=&#34;10&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;560&#34; y=&#34;384&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;W4&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;373&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;CPU core 4&lt;/text&gt;&#xA;    &lt;text x=&#34;672&#34; y=&#34;394&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;:3000&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 398 210 L 516 119&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M516,119 l-3,13 l12,-6 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 398 214 L 516 205&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M516,205 l-13,-4 l4,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 398 222 L 516 291&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M516,291 l-3,-13 l12,6 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 398 230 L 516 377&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M516,377 l-3,-13 l12,6 z&#34;/&gt;&#xA;&#xA;  &lt;text x=&#34;960&#34; y=&#34;200&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;Каждый воркер —&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;224&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;отдельный процесс&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;256&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;общее состояние —&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;в Redis или БД&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Cluster: главный процесс раздаёт запросы воркерам по ядрам&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Debounce и throttle в JavaScript: укрощаем события</title>
      <link>https://hackerx.ru/js-debounce-throttle/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-debounce-throttle/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Частые события&lt;/strong&gt; (ввод, прокрутка, ресайз) срабатывают десятки раз в секунду — реагировать на каждое дорого.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Debounce ждёт паузу:&lt;/strong&gt; выполняет функцию, когда события прекратились — для живого поиска, автосохранения.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Throttle ограничивает частоту:&lt;/strong&gt; не чаще раза в интервал — для прокрутки, движения мыши.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Разница:&lt;/strong&gt; debounce = «конец серии», throttle = «равномерно во время серии».&lt;/li&gt;&#xA;&lt;li&gt;Обе строятся на &lt;a href=&#34;https://hackerx.ru/node-timers/&#34;&gt;таймерах&lt;/a&gt; и &lt;a href=&#34;https://hackerx.ru/js-closures/&#34;&gt;замыканиях&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>ES-модули в JavaScript: import и export</title>
      <link>https://hackerx.ru/js-es-modules/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-es-modules/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;ES-модули&lt;/strong&gt; разбивают код на файлы: &lt;code&gt;export&lt;/code&gt; отдаёт значения, &lt;code&gt;import&lt;/code&gt; подключает.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Именованный экспорт&lt;/strong&gt; — несколько значений по именам (импорт в &lt;code&gt;{ }&lt;/code&gt;); &lt;strong&gt;дефолтный&lt;/strong&gt; — одно главное (имя любое).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;import&lt;/code&gt; (ESM)&lt;/strong&gt; — стандарт языка; &lt;strong&gt;&lt;code&gt;require&lt;/code&gt; (CommonJS)&lt;/strong&gt; — старый формат &lt;a href=&#34;https://hackerx.ru/node-esm-vs-cjs/&#34;&gt;Node.js&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Включить в Node:&lt;/strong&gt; &lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt; в package.json или &lt;code&gt;.mjs&lt;/code&gt;; в браузере — &lt;code&gt;type=&amp;quot;module&amp;quot;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Динамический &lt;code&gt;import()&lt;/code&gt;&lt;/strong&gt; — загрузка по требованию, возвращает промис.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>ESM против CommonJS: import и require в Node.js</title>
      <link>https://hackerx.ru/node-esm-vs-cjs/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-esm-vs-cjs/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;В Node два формата модулей: &lt;strong&gt;ESM&lt;/strong&gt; (&lt;code&gt;import&lt;/code&gt;/&lt;code&gt;export&lt;/code&gt;) и &lt;strong&gt;CommonJS&lt;/strong&gt; (&lt;code&gt;require&lt;/code&gt;/&lt;code&gt;module.exports&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для нового кода — ESM:&lt;/strong&gt; стандарт языка, тот же синтаксис в браузере, статический анализ, top-level await.&lt;/li&gt;&#xA;&lt;li&gt;Включается через &lt;strong&gt;&lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt;&lt;/strong&gt; в package.json или расширение &lt;code&gt;.mjs&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;__dirname&lt;/code&gt; в ESM нет&lt;/strong&gt; — его заменяет &lt;code&gt;import.meta.dirname&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;CommonJS не мёртв: он в миллионах пакетов и продолжит работать. Но новое на нём не пишут.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Event Loop в Node.js: фазы и порядок выполнения</title>
      <link>https://hackerx.ru/node-event-loop/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-event-loop/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Событийный цикл — бесконечный цикл в libuv, который спрашивает: &lt;strong&gt;что готово выполниться сейчас?&lt;/strong&gt; Он проходит шесть фаз по кругу.&lt;/li&gt;&#xA;&lt;li&gt;Между фазами и после каждого колбэка разбирается &lt;strong&gt;очередь микрозадач&lt;/strong&gt; (промисы) — поэтому промис всегда раньше таймера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;process.nextTick&lt;/code&gt; — отдельная очередь&lt;/strong&gt; с приоритетом выше промисов, но её порядок зависит от контекста вызова.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;setTimeout(0)&lt;/code&gt; не значит «немедленно»:&lt;/strong&gt; ноль — минимальная задержка, колбэк ждёт фазы timers.&lt;/li&gt;&#xA;&lt;li&gt;Пока выполняется ваш синхронный код, &lt;strong&gt;цикл стоит&lt;/strong&gt; — блокировка одинаково страшна и для диска, и для процессора.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Схема: колбэки ждут в очереди, событийный цикл проходит фазы timers, poll, check, close и передаёт колбэк в стек вызовов, когда стек пуст&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;NODE.JS · СОБЫТИЙНЫЙ ЦИКЛ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;60&#34; y=&#34;96&#34; width=&#34;230&#34; height=&#34;266&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;60&#34; y=&#34;96&#34; width=&#34;230&#34; height=&#34;266&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;130&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Call Stack&lt;/text&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;270&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;270&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;292&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;main()&lt;/text&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;228&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-panel-2&#34;/&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;228&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;250&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;fn()&lt;/text&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;186&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-panel-2&#34;/&gt;&#xA;  &lt;rect x=&#34;92&#34; y=&#34;186&#34; width=&#34;166&#34; height=&#34;34&#34; rx=&#34;6&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;208&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;cb()&lt;/text&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;340&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;LIFO · один поток&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;circle cx=&#34;600&#34; cy=&#34;229&#34; r=&#34;128&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;circle cx=&#34;600&#34; cy=&#34;229&#34; r=&#34;128&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;223&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;event&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;246&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;loop&lt;/text&gt;&#xA;  &#xA;  &lt;path d=&#34;M 600 78 A 151 151 0 0 1 735 165&#34; class=&#34;il-arrow-a&#34;/&gt;&#xA;  &lt;path class=&#34;il-ah-a&#34; d=&#34;M735,165 l-3,-13 l12,5 z&#34;/&gt;&#xA;  &#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;536&#34; y=&#34;86&#34; width=&#34;128&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;536&#34; y=&#34;86&#34; width=&#34;128&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;600&#34; y=&#34;108&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;timers&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;712&#34; y=&#34;212&#34; width=&#34;120&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;712&#34; y=&#34;212&#34; width=&#34;120&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;772&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;poll&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;536&#34; y=&#34;338&#34; width=&#34;128&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;536&#34; y=&#34;338&#34; width=&#34;128&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;600&#34; y=&#34;360&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;check&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;368&#34; y=&#34;212&#34; width=&#34;120&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;368&#34; y=&#34;212&#34; width=&#34;120&#34; height=&#34;34&#34; rx=&#34;17&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;428&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;close&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;910&#34; y=&#34;96&#34; width=&#34;230&#34; height=&#34;266&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;910&#34; y=&#34;96&#34; width=&#34;230&#34; height=&#34;266&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1025&#34; y=&#34;130&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Очередь&lt;/text&gt;&#xA;  &lt;rect x=&#34;942&#34; y=&#34;160&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;942&#34; y=&#34;160&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1025&#34; y=&#34;184&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;setTimeout&lt;/text&gt;&#xA;  &lt;rect x=&#34;942&#34; y=&#34;210&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;942&#34; y=&#34;210&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1025&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;on(&#39;data&#39;)&lt;/text&gt;&#xA;  &lt;rect x=&#34;942&#34; y=&#34;260&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;942&#34; y=&#34;260&#34; width=&#34;166&#34; height=&#34;38&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1025&#34; y=&#34;284&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;.then()&lt;/text&gt;&#xA;  &lt;text x=&#34;1025&#34; y=&#34;340&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;колбэки ждут&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 905 229 L 745 229&#34; class=&#34;il-arrow&#34;/&gt;&#xA;  &lt;path class=&#34;il-ah&#34; d=&#34;M745,229 l13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;825&#34; y=&#34;215&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;берёт колбэк&lt;/text&gt;&#xA;  &lt;path d=&#34;M 466 229 L 300 229&#34; class=&#34;il-arrow-a&#34;/&gt;&#xA;  &lt;path class=&#34;il-ah-a&#34; d=&#34;M300,229 l13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;383&#34; y=&#34;215&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;когда стек пуст&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Один оборот событийного цикла: очередь → цикл фаз → стек вызовов&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;p&gt;Событийный цикл — то, что отличает &lt;a href=&#34;https://hackerx.ru/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-node-js/&#34;&gt;Node.js&lt;/a&gt; от «просто JavaScript на сервере». Понять его порядок один раз — значит перестать удивляться, почему код выполняется не так, как написан.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Express с нуля: первый сервер за 10 минут</title>
      <link>https://hackerx.ru/express-getting-started/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-getting-started/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Express — минималистичный веб-фреймворк&lt;/strong&gt; для Node.js: берёт на себя маршруты, разбор запросов, отправку ответов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Зачем не голый &lt;a href=&#34;https://hackerx.ru/node-js-for-beginners-create-a-http-server/&#34;&gt;http&lt;/a&gt;:&lt;/strong&gt; там маршруты и разбор тела пишут вручную; Express даёт это из коробки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Минимальный сервер:&lt;/strong&gt; &lt;code&gt;express()&lt;/code&gt; → &lt;code&gt;app.get(...)&lt;/code&gt; → &lt;code&gt;app.listen(port)&lt;/code&gt; — несколько строк.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;req&lt;/code&gt;&lt;/strong&gt; — запрос (параметры, тело, заголовки), &lt;strong&gt;&lt;code&gt;res&lt;/code&gt;&lt;/strong&gt; — ответ (&lt;code&gt;res.json&lt;/code&gt;, &lt;code&gt;res.send&lt;/code&gt;, &lt;code&gt;res.status&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Остаётся стандартом&lt;/strong&gt; экосистемы Node, несмотря на быстрые альтернативы.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Fetch в JavaScript: запросы к серверу без боли</title>
      <link>https://hackerx.ru/js-fetch-ajax/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-fetch-ajax/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;fetch(url)&lt;/code&gt;&lt;/strong&gt; — HTTP-запрос, возвращает промис; встроен в браузер и &lt;a href=&#34;https://hackerx.ru/node-fetch-http-client/&#34;&gt;Node.js&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ловушка: &lt;code&gt;fetch&lt;/code&gt; не бросает на 404/500&lt;/strong&gt; — проверяйте &lt;code&gt;response.ok&lt;/code&gt; вручную.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Два &lt;code&gt;await&lt;/code&gt;:&lt;/strong&gt; первый ждёт ответ (заголовки), второй — &lt;code&gt;response.json()&lt;/code&gt; (тело).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;POST с JSON:&lt;/strong&gt; &lt;code&gt;method&lt;/code&gt;, заголовок &lt;code&gt;Content-Type&lt;/code&gt;, &lt;code&gt;body: JSON.stringify(data)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Отмена&lt;/strong&gt; — через &lt;code&gt;AbortController&lt;/code&gt; (устаревший поисковый запрос и т.п.).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Клиент шлёт запрос серверу, получает ответ и проверяет response.ok — успех разбирается через json, ошибки 404 и 500 бросаются вручную&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · FETCH&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;60&#34; y=&#34;150&#34; width=&#34;230&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;60&#34; y=&#34;150&#34; width=&#34;230&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;196&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Клиент&lt;/text&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;228&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;await fetch(url)&lt;/text&gt;&#xA;  &lt;text x=&#34;175&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;браузер или Node&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;470&#34; y=&#34;150&#34; width=&#34;230&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;470&#34; y=&#34;150&#34; width=&#34;230&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;585&#34; y=&#34;196&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Сервер&lt;/text&gt;&#xA;  &lt;text x=&#34;585&#34; y=&#34;228&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;API&lt;/text&gt;&#xA;  &lt;text x=&#34;585&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;отвечает статусом&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 292 200 L 466 200&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M466,200 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;379&#34; y=&#34;188&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;request&lt;/text&gt;&#xA;  &lt;path d=&#34;M 466 258 L 292 258&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M292,258 l13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;379&#34; y=&#34;284&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;response&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 702 225 L 792 225&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M792,225 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;rect x=&#34;800&#34; y=&#34;176&#34; width=&#34;150&#34; height=&#34;98&#34; rx=&#34;12&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;800&#34; y=&#34;176&#34; width=&#34;150&#34; height=&#34;98&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;875&#34; y=&#34;214&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;response&lt;/text&gt;&#xA;  &lt;text x=&#34;875&#34; y=&#34;240&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;.ok ?&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;1000&#34; y=&#34;110&#34; width=&#34;160&#34; height=&#34;76&#34; rx=&#34;10&#34; class=&#34;il-ok-soft&#34;/&gt;&lt;rect x=&#34;1000&#34; y=&#34;110&#34; width=&#34;160&#34; height=&#34;76&#34; rx=&#34;10&#34; class=&#34;il-ok-line&#34;/&gt;&#xA;  &lt;text x=&#34;1080&#34; y=&#34;144&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34; style=&#34;fill:#1baf7a&#34;&gt;.json()&lt;/text&gt;&#xA;  &lt;text x=&#34;1080&#34; y=&#34;168&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;200–299&lt;/text&gt;&#xA;  &lt;rect x=&#34;1000&#34; y=&#34;264&#34; width=&#34;160&#34; height=&#34;76&#34; rx=&#34;10&#34; class=&#34;il-bad-soft&#34;/&gt;&lt;rect x=&#34;1000&#34; y=&#34;264&#34; width=&#34;160&#34; height=&#34;76&#34; rx=&#34;10&#34; class=&#34;il-bad-line&#34;/&gt;&#xA;  &lt;text x=&#34;1080&#34; y=&#34;298&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34; style=&#34;fill:#e34948&#34;&gt;throw&lt;/text&gt;&#xA;  &lt;text x=&#34;1080&#34; y=&#34;322&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;404 / 500&lt;/text&gt;&#xA;  &lt;path d=&#34;M 950 205 L 996 158&#34; class=&#34;il-ok-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M996,158 l-3,13 l12,-6 z&#34; style=&#34;fill:#1baf7a&#34;/&gt;&#xA;  &lt;path d=&#34;M 950 245 L 996 292&#34; class=&#34;il-bad-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M996,292 l-3,-13 l12,6 z&#34; style=&#34;fill:#e34948&#34;/&gt;&#xA;&#xA;  &lt;text x=&#34;585&#34; y=&#34;352&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;FETCH НЕ БРОСАЕТ НА 404/500 — ПРОВЕРЯЙ response.ok САМ&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;fetch: запрос, ответ и проверка response.ok&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Graceful shutdown в Node.js: корректное завершение сервера</title>
      <link>https://hackerx.ru/node-graceful-shutdown/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-graceful-shutdown/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Graceful shutdown — корректное завершение:&lt;/strong&gt; перестать принимать новые запросы, доделать текущие, закрыть соединения, выйти.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Зачем:&lt;/strong&gt; при деплое/перезапуске мгновенное убийство обрывает запросы и портит данные.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Перехват сигналов:&lt;/strong&gt; &lt;code&gt;process.on(&#39;SIGTERM&#39;)&lt;/code&gt; (оркестратор) и &lt;code&gt;SIGINT&lt;/code&gt; (Ctrl+C).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;В обработчике:&lt;/strong&gt; &lt;code&gt;server.close()&lt;/code&gt;, дождаться запросов, закрыть &lt;a href=&#34;https://hackerx.ru/chto-takoe-mongodb/&#34;&gt;БД&lt;/a&gt;, &lt;code&gt;process.exit&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Таймаут обязателен&lt;/strong&gt; — зависший запрос не должен блокировать остановку навсегда.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>HTTP-клиент в Node.js: fetch и запросы к API</title>
      <link>https://hackerx.ru/node-fetch-http-client/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-fetch-http-client/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;fetch&lt;/code&gt; встроен в Node.js&lt;/strong&gt; с версии 18 — тот же API, что &lt;a href=&#34;https://hackerx.ru/js-fetch-ajax/&#34;&gt;в браузере&lt;/a&gt;, без установки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ловушка та же:&lt;/strong&gt; &lt;code&gt;fetch&lt;/code&gt; не бросает на 404/500 — проверяйте &lt;code&gt;response.ok&lt;/code&gt; вручную.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Таймаут:&lt;/strong&gt; &lt;code&gt;AbortSignal.timeout(мс)&lt;/code&gt; в &lt;code&gt;signal&lt;/code&gt; — на сервере обязателен, иначе зависший API блокирует.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;axios больше не нужен&lt;/strong&gt; для простых запросов — встроенного &lt;code&gt;fetch&lt;/code&gt; хватает.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Отличие от браузера:&lt;/strong&gt; нет CORS и куки, но нужны таймауты, повторы, обработка сбоев внешних API.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>JSON в JavaScript: parse, stringify и подводные камни</title>
      <link>https://hackerx.ru/js-json/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-json/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;JSON — текстовый формат&lt;/strong&gt;, объект — структура в памяти. &lt;code&gt;parse&lt;/code&gt; строит объект из строки, &lt;code&gt;stringify&lt;/code&gt; — строку из объекта.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;JSON.stringify(obj, null, 2)&lt;/code&gt;&lt;/strong&gt; — форматирование с отступами для логов и файлов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Теряется при сериализации:&lt;/strong&gt; функции, &lt;code&gt;undefined&lt;/code&gt;, символы пропадают; &lt;code&gt;Date&lt;/code&gt; → строка; &lt;code&gt;Map&lt;/code&gt;/&lt;code&gt;Set&lt;/code&gt; → &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;JSON.parse&lt;/code&gt; бросает&lt;/strong&gt; на невалидной строке — оборачивайте в &lt;code&gt;try/catch&lt;/code&gt; для внешних данных.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Глубокая копия:&lt;/strong&gt; старый трюк &lt;code&gt;JSON.parse(JSON.stringify())&lt;/code&gt; заменён на &lt;code&gt;structuredClone&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>JWT-авторизация в Express: токены на практике</title>
      <link>https://hackerx.ru/express-jwt-auth/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-jwt-auth/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;JWT — подписанный токен&lt;/strong&gt;, который сервер выдаёт после входа; клиент шлёт его с каждым запросом вместо пароля.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Самодостаточен:&lt;/strong&gt; данные внутри токена, сервер ничего не хранит, проверяет подпись.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Проверка — &lt;a href=&#34;https://hackerx.ru/express-middleware/&#34;&gt;middleware&lt;/a&gt;:&lt;/strong&gt; читает токен, проверяет подпись, кладёт пользователя в &lt;code&gt;req&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Хранение на клиенте:&lt;/strong&gt; &lt;code&gt;httpOnly&lt;/code&gt;-cookie (безопаснее) против &lt;a href=&#34;https://hackerx.ru/js-localstorage/&#34;&gt;localStorage&lt;/a&gt; (уязвим к XSS).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ошибки:&lt;/strong&gt; секрет в коде, токен без срока, чувствительные данные внутри (JWT &lt;strong&gt;не зашифрован&lt;/strong&gt;, лишь подписан).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Токен JWT из трёх частей — header, payload, signature — и поток: вход по паролю, подпись секретом, проверка подписи на сервере&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;EXPRESS · JWT-АВТОРИЗАЦИЯ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;150&#34; y=&#34;80&#34; width=&#34;230&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;150&#34; y=&#34;80&#34; width=&#34;230&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;265&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;header&lt;/text&gt;&#xA;  &lt;text x=&#34;392&#34; y=&#34;120&#34; text-anchor=&#34;middle&#34; class=&#34;il-h&#34;&gt;.&lt;/text&gt;&#xA;  &lt;rect x=&#34;404&#34; y=&#34;80&#34; width=&#34;330&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;404&#34; y=&#34;80&#34; width=&#34;330&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;569&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;payload · userId, exp&lt;/text&gt;&#xA;  &lt;text x=&#34;746&#34; y=&#34;120&#34; text-anchor=&#34;middle&#34; class=&#34;il-h&#34;&gt;.&lt;/text&gt;&#xA;  &lt;rect x=&#34;758&#34; y=&#34;80&#34; width=&#34;292&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-warn-soft&#34;/&gt;&lt;rect x=&#34;758&#34; y=&#34;80&#34; width=&#34;292&#34; height=&#34;64&#34; rx=&#34;10&#34; class=&#34;il-warn-line&#34;/&gt;&#xA;  &lt;text x=&#34;904&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34; style=&#34;fill:#eda100&#34;&gt;signature&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;176&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;base64: содержимое читается любым — подпись защищает от подделки, но не шифрует&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;80&#34; y=&#34;238&#34; width=&#34;300&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;80&#34; y=&#34;238&#34; width=&#34;300&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;230&#34; y=&#34;276&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Вход по паролю&lt;/text&gt;&#xA;  &lt;text x=&#34;230&#34; y=&#34;308&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;jwt.sign(data, secret)&lt;/text&gt;&#xA;  &lt;text x=&#34;230&#34; y=&#34;344&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;выдаёт токен&lt;/text&gt;&#xA;&#xA;  &lt;rect x=&#34;450&#34; y=&#34;238&#34; width=&#34;260&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;450&#34; y=&#34;238&#34; width=&#34;260&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;580&#34; y=&#34;276&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Клиент&lt;/text&gt;&#xA;  &lt;text x=&#34;580&#34; y=&#34;308&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;хранит токен&lt;/text&gt;&#xA;  &lt;text x=&#34;580&#34; y=&#34;344&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;шлёт с каждым запросом&lt;/text&gt;&#xA;&#xA;  &lt;rect x=&#34;780&#34; y=&#34;238&#34; width=&#34;330&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;780&#34; y=&#34;238&#34; width=&#34;330&#34; height=&#34;130&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;945&#34; y=&#34;276&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Проверка&lt;/text&gt;&#xA;  &lt;text x=&#34;945&#34; y=&#34;308&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;jwt.verify(token, secret)&lt;/text&gt;&#xA;  &lt;text x=&#34;945&#34; y=&#34;344&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;подпись верна → req.user&lt;/text&gt;&#xA;&#xA;  &lt;path d=&#34;M 384 303 L 446 303&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M446,303 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 714 303 L 776 303&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M776,303 l-13,-6 l0,12 z&#34;/&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;JWT: три части токена и цикл подпись → проверка&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>localStorage в JavaScript: хранение данных в браузере</title>
      <link>https://hackerx.ru/js-localstorage/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-localstorage/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/strong&gt; хранит пары ключ-значение в браузере, переживает перезагрузку и закрытие вкладки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Хранит только строки:&lt;/strong&gt; объекты пишут через &lt;a href=&#34;https://hackerx.ru/js-json/&#34;&gt;&lt;code&gt;JSON.stringify&lt;/code&gt;&lt;/a&gt;, читают через &lt;code&gt;JSON.parse&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;sessionStorage&lt;/code&gt;&lt;/strong&gt; — тот же API, но данные живут только в пределах вкладки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Никогда не храните пароли и токены&lt;/strong&gt; — доступно любому JS на странице (XSS).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Лимит ~5–10 МБ&lt;/strong&gt; на домен; для больших данных — IndexedDB.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Map и Set в JavaScript: когда не хватает объекта</title>
      <link>https://hackerx.ru/js-map-set/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-map-set/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Map&lt;/code&gt;&lt;/strong&gt; — пары ключ-значение, где &lt;strong&gt;ключ любого типа&lt;/strong&gt; (объект, число), с порядком вставки и &lt;code&gt;size&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/strong&gt; — коллекция &lt;strong&gt;уникальных значений&lt;/strong&gt;; дубликаты отбрасываются автоматически.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Убрать дубли из массива:&lt;/strong&gt; &lt;code&gt;[...new Set(arr)]&lt;/code&gt; — самый короткий способ.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Перебор&lt;/strong&gt; обоих через &lt;code&gt;for...of&lt;/code&gt;; &lt;code&gt;has&lt;/code&gt; проверяет принадлежность за постоянное время.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Объект&lt;/strong&gt; — для фиксированной структуры; &lt;strong&gt;Map&lt;/strong&gt; — для динамических ключей, частых add/delete, размера.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Set отбрасывает дубликаты и хранит уникальные значения; Map связывает ключи любого типа со значениями&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · MAP И SET&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;46&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;46&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;311&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Set — только уникальные&lt;/text&gt;&#xA;  &#xA;  &lt;text x=&#34;311&#34; y=&#34;156&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;add(1) add(2) add(2) add(3) add(1)&lt;/text&gt;&#xA;  &lt;path d=&#34;M 311 172 L 311 208&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M311,208 l-6,-13 l12,0 z&#34;/&gt;&#xA;  &#xA;  &lt;rect x=&#34;150&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;150&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;185&#34; y=&#34;265&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;1&lt;/text&gt;&#xA;  &lt;rect x=&#34;276&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;276&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;311&#34; y=&#34;265&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;2&lt;/text&gt;&#xA;  &lt;rect x=&#34;402&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;402&#34; y=&#34;222&#34; width=&#34;70&#34; height=&#34;70&#34; rx=&#34;10&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;437&#34; y=&#34;265&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;3&lt;/text&gt;&#xA;  &lt;text x=&#34;311&#34; y=&#34;342&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;дубликаты отброшены · [...new Set(arr)]&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;624&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;624&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;889&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Map — ключ любого типа&lt;/text&gt;&#xA;  &#xA;  &lt;rect x=&#34;668&#34; y=&#34;150&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;668&#34; y=&#34;150&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;758&#34; y=&#34;179&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;&#39;name&#39;&lt;/text&gt;&#xA;  &lt;path d=&#34;M 856 173 L 908 173&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M908,173 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;rect x=&#34;916&#34; y=&#34;150&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;916&#34; y=&#34;150&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;1016&#34; y=&#34;179&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;&#39;Аня&#39;&lt;/text&gt;&#xA;&#xA;  &lt;rect x=&#34;668&#34; y=&#34;210&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;668&#34; y=&#34;210&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;758&#34; y=&#34;239&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;42&lt;/text&gt;&#xA;  &lt;path d=&#34;M 856 233 L 908 233&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M908,233 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;rect x=&#34;916&#34; y=&#34;210&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;916&#34; y=&#34;210&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;1016&#34; y=&#34;239&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;&#39;ответ&#39;&lt;/text&gt;&#xA;&#xA;  &lt;rect x=&#34;668&#34; y=&#34;270&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;668&#34; y=&#34;270&#34; width=&#34;180&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;758&#34; y=&#34;299&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;{obj}&lt;/text&gt;&#xA;  &lt;path d=&#34;M 856 293 L 908 293&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M908,293 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;rect x=&#34;916&#34; y=&#34;270&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;916&#34; y=&#34;270&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;1016&#34; y=&#34;299&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;&#39;данные&#39;&lt;/text&gt;&#xA;&#xA;  &lt;text x=&#34;889&#34; y=&#34;348&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;строка · число · объект — как ключ · есть .size&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Set хранит уникальные значения, Map — ключ любого типа&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Middleware в Express: сердце фреймворка</title>
      <link>https://hackerx.ru/express-middleware/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-middleware/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Middleware — функция между запросом и ответом&lt;/strong&gt; с доступом к &lt;code&gt;req&lt;/code&gt;, &lt;code&gt;res&lt;/code&gt;, &lt;code&gt;next&lt;/code&gt;. На них построен весь Express.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;next()&lt;/code&gt;&lt;/strong&gt; передаёт управление дальше по цепочке; без него запрос &lt;strong&gt;зависнет&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Порядок = порядок подключения&lt;/strong&gt; сверху вниз: разбор тела и логи — раньше маршрутов, ошибки — в конце.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Глобальный&lt;/strong&gt; (&lt;code&gt;app.use&lt;/code&gt;) — на все запросы; &lt;strong&gt;маршрутный&lt;/strong&gt; — только на конкретный.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Своё middleware:&lt;/strong&gt; функция &lt;code&gt;(req, res, next)&lt;/code&gt; → логика → &lt;code&gt;next()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Запрос проходит через цепочку middleware — logger, express.json, auth — к обработчику маршрута и ответу; каждое передаёт управление через next&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;EXPRESS · MIDDLEWARE&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;34&#34; y=&#34;176&#34; width=&#34;120&#34; height=&#34;78&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;34&#34; y=&#34;176&#34; width=&#34;120&#34; height=&#34;78&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;94&#34; y=&#34;210&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;req&lt;/text&gt;&#xA;  &lt;text x=&#34;94&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;запрос&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;206&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;206&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;281&#34; y=&#34;208&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;logger&lt;/text&gt;&#xA;    &lt;text x=&#34;281&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;next()&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;408&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;408&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;483&#34; y=&#34;208&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;express.json&lt;/text&gt;&#xA;    &lt;text x=&#34;483&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;next()&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;610&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;610&#34; y=&#34;170&#34; width=&#34;150&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;    &lt;text x=&#34;685&#34; y=&#34;208&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;auth&lt;/text&gt;&#xA;    &lt;text x=&#34;685&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;next()&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;  &lt;g&gt;&#xA;    &lt;rect x=&#34;812&#34; y=&#34;170&#34; width=&#34;176&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;812&#34; y=&#34;170&#34; width=&#34;176&#34; height=&#34;90&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;    &lt;text x=&#34;900&#34; y=&#34;208&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;route handler&lt;/text&gt;&#xA;    &lt;text x=&#34;900&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;res.json()&lt;/text&gt;&#xA;  &lt;/g&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;1040&#34; y=&#34;176&#34; width=&#34;120&#34; height=&#34;78&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;1040&#34; y=&#34;176&#34; width=&#34;120&#34; height=&#34;78&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;1100&#34; y=&#34;210&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;res&lt;/text&gt;&#xA;  &lt;text x=&#34;1100&#34; y=&#34;234&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;ответ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 156 215 L 202 215&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M202,215 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 358 215 L 404 215&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M404,215 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 560 215 L 606 215&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M606,215 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 762 215 L 808 215&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M808,215 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 990 215 L 1036 215&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M1036,215 l-13,-6 l0,12 z&#34;/&gt;&#xA;&#xA;  &lt;text x=&#34;600&#34; y=&#34;120&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;Каждое middleware может проверить или дополнить запрос и передать дальше через &lt;tspan class=&#34;il-mono&#34;&gt;next()&lt;/tspan&gt;&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;322&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;ПОРЯДОК ВАЖЕН · ВЫПОЛНЯЮТСЯ СВЕРХУ ВНИЗ&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Конвейер middleware: запрос проходит через функции к ответу&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>REPL в Node.js: интерактивная консоль для экспериментов</title>
      <link>https://hackerx.ru/node-repl/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-repl/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;REPL — интерактивная консоль Node.js:&lt;/strong&gt; вводишь код, сразу видишь результат. Запуск — &lt;code&gt;node&lt;/code&gt; без файла.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Read-Eval-Print-Loop:&lt;/strong&gt; читает строку, выполняет, печатает, ждёт следующую.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Переменная &lt;code&gt;_&lt;/code&gt;&lt;/strong&gt; хранит результат последнего выражения.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Команды с точкой:&lt;/strong&gt; &lt;code&gt;.help&lt;/code&gt;, &lt;code&gt;.load файл&lt;/code&gt;, &lt;code&gt;.save файл&lt;/code&gt;, &lt;code&gt;.editor&lt;/code&gt;, &lt;code&gt;.exit&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Удобен для быстрых проверок&lt;/strong&gt; функции или незнакомого API без создания скрипта.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>REST API на Express: строим по правилам</title>
      <link>https://hackerx.ru/express-rest-api/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-rest-api/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;REST — API вокруг ресурсов и методов HTTP:&lt;/strong&gt; путь = существительное (&lt;code&gt;/users&lt;/code&gt;), действие = метод.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CRUD:&lt;/strong&gt; &lt;code&gt;GET&lt;/code&gt; (читать), &lt;code&gt;POST&lt;/code&gt; (создать), &lt;code&gt;PUT&lt;/code&gt;/&lt;code&gt;PATCH&lt;/code&gt; (обновить), &lt;code&gt;DELETE&lt;/code&gt; (удалить).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Коды ответов:&lt;/strong&gt; 200 (ок), 201 (создано), 204 (удалено), 400/401/404 (ошибки клиента), 500 (сервер).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Версионирование&lt;/strong&gt; через префикс &lt;code&gt;/api/v1&lt;/code&gt; — менять API, не ломая клиентов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Частая ошибка:&lt;/strong&gt; глаголы в путях (&lt;code&gt;/getUser&lt;/code&gt;) вместо ресурсов (&lt;code&gt;/users/:id&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Spread и rest в JavaScript: три точки</title>
      <link>https://hackerx.ru/js-spread-rest/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-spread-rest/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Три точки &lt;code&gt;...&lt;/code&gt; — два разных смысла по месту:&lt;/strong&gt; spread разворачивает, rest собирает.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Spread&lt;/strong&gt; (в вызове/литерале): &lt;code&gt;[...a, ...b]&lt;/code&gt;, &lt;code&gt;{ ...obj }&lt;/code&gt; — копирование и слияние.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Rest&lt;/strong&gt; (в параметрах/деструктуризации): &lt;code&gt;function f(...args)&lt;/code&gt; — собрать всё в массив.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Копия поверхностная:&lt;/strong&gt; вложенное остаётся общим, для глубокой — &lt;code&gt;structuredClone&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Rest в параметрах — современная замена старому объекту &lt;code&gt;arguments&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Symbol в JavaScript: зачем нужны символы</title>
      <link>https://hackerx.ru/js-symbol/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-symbol/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Symbol&lt;/code&gt; — примитив, каждое значение уникально:&lt;/strong&gt; &lt;code&gt;Symbol(&#39;id&#39;) !== Symbol(&#39;id&#39;)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Применение — уникальные ключи свойств&lt;/strong&gt;, которые гарантированно ни с чем не столкнутся.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Символьные ключи скрыты&lt;/strong&gt; от &lt;code&gt;Object.keys&lt;/code&gt;, &lt;code&gt;for...in&lt;/code&gt; и &lt;code&gt;JSON.stringify&lt;/code&gt; — удобно для метаданных.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Well-known symbols&lt;/strong&gt; (&lt;code&gt;Symbol.iterator&lt;/code&gt;) настраивают поведение объектов в языке.&lt;/li&gt;&#xA;&lt;li&gt;В повседневном коде создают редко; знать полезно ради понимания &lt;code&gt;for...of&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>this в JavaScript: четыре правила связывания</title>
      <link>https://hackerx.ru/js-this-context/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-this-context/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;this&lt;/code&gt; определяется тем, КАК вызвана функция, а не где объявлена.&lt;/strong&gt; Это ключ ко всему.&lt;/li&gt;&#xA;&lt;li&gt;Четыре правила: &lt;strong&gt;метод объекта&lt;/strong&gt; → объект; &lt;strong&gt;сама по себе&lt;/strong&gt; → undefined (строгий режим); &lt;strong&gt;&lt;code&gt;new&lt;/code&gt;&lt;/strong&gt; → новый объект; &lt;strong&gt;&lt;code&gt;call&lt;/code&gt;/&lt;code&gt;apply&lt;/code&gt;/&lt;code&gt;bind&lt;/code&gt;&lt;/strong&gt; → что передали.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;this&lt;/code&gt; теряется в колбэках&lt;/strong&gt;, потому что там функция вызывается сама по себе, а не как метод.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;У стрелочной функции нет своего &lt;code&gt;this&lt;/code&gt;&lt;/strong&gt; — она берёт его из окружения. Отсюда: хороша в колбэках, плоха как метод.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;bind&lt;/code&gt; возвращает функцию с намертво привязанным &lt;code&gt;this&lt;/code&gt;; &lt;code&gt;call&lt;/code&gt;/&lt;code&gt;apply&lt;/code&gt; вызывают сразу.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Transform-потоки в Node.js: обработка данных на лету</title>
      <link>https://hackerx.ru/node-transform-streams/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-transform-streams/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Transform-поток&lt;/strong&gt; читает и пишет одновременно, преобразуя данные &lt;strong&gt;по кускам на лету&lt;/strong&gt; (сжатие, парсинг, шифрование).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Держит в памяти лишь текущий фрагмент&lt;/strong&gt; — потому справляется с данными любого размера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Соединяют через &lt;code&gt;pipeline&lt;/code&gt;&lt;/strong&gt;, а не &lt;code&gt;pipe&lt;/code&gt;: &lt;code&gt;pipeline&lt;/code&gt; корректно ловит ошибки и закрывает все потоки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Свой Transform:&lt;/strong&gt; метод &lt;code&gt;transform(chunk, enc, cb)&lt;/code&gt; преобразует каждый кусок.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Противодавление&lt;/strong&gt; (backpressure) управляется автоматически — быстрый источник ждёт медленного получателя.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Конвейер потоков: Readable-источник, Transform-преобразование и Writable-приёмник; данные идут кусками, в памяти только текущий фрагмент&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;NODE.JS · ПОТОКИ И PIPELINE&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;46&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;46&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;166&#34; y=&#34;190&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Readable&lt;/text&gt;&#xA;  &lt;text x=&#34;166&#34; y=&#34;220&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;createReadStream&lt;/text&gt;&#xA;  &lt;text x=&#34;166&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;источник · файл 4 ГБ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;480&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;480&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;190&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Transform&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;220&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;gzip / parse&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;преобразует на лету&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;914&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;914&#34; y=&#34;150&#34; width=&#34;240&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1034&#34; y=&#34;190&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Writable&lt;/text&gt;&#xA;  &lt;text x=&#34;1034&#34; y=&#34;220&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;createWriteStream&lt;/text&gt;&#xA;  &lt;text x=&#34;1034&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;приёмник&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;312&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent&#34;/&gt;&#xA;  &lt;rect x=&#34;350&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;388&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent&#34;/&gt;&#xA;  &lt;path d=&#34;M 292 240 L 474 240&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M474,240 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &#xA;  &lt;rect x=&#34;746&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent&#34;/&gt;&#xA;  &lt;rect x=&#34;784&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;822&#34; y=&#34;205&#34; width=&#34;20&#34; height=&#34;20&#34; rx=&#34;4&#34; class=&#34;il-accent&#34;/&gt;&#xA;  &lt;path d=&#34;M 726 240 L 908 240&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M908,240 l-13,-6 l0,12 z&#34;/&gt;&#xA;&#xA;  &lt;text x=&#34;600&#34; y=&#34;112&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;Данные идут кусками: в памяти — только текущий фрагмент, а не весь файл&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;352&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;pipeline() СОЕДИНЯЕТ ПОТОКИ И ЗАКРЫВАЕТ ИХ ПРИ ОШИБКЕ&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Поток данных: источник → преобразование → приёмник по кускам&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>URL и строка запроса в Node.js: разбор и сборка</title>
      <link>https://hackerx.ru/node-url-querystring/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-url-querystring/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Класс &lt;code&gt;URL&lt;/code&gt;&lt;/strong&gt; — стандартный разбор: &lt;code&gt;new URL(str)&lt;/code&gt; даёт &lt;code&gt;protocol&lt;/code&gt;, &lt;code&gt;hostname&lt;/code&gt;, &lt;code&gt;pathname&lt;/code&gt;, &lt;code&gt;searchParams&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;url.searchParams&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;URLSearchParams&lt;/code&gt;) — работа с query: &lt;code&gt;get&lt;/code&gt;, &lt;code&gt;getAll&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;append&lt;/code&gt;, &lt;code&gt;delete&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Кодирование автоматическое&lt;/strong&gt; — &lt;code&gt;searchParams.set&lt;/code&gt; сам экранирует пробелы, кириллицу, спецсимволы.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Модуль &lt;code&gt;querystring&lt;/code&gt; устарел&lt;/strong&gt; — его заменил &lt;code&gt;URLSearchParams&lt;/code&gt; (одинаковый в браузере и Node).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Сборка:&lt;/strong&gt; создать &lt;code&gt;URL&lt;/code&gt;, добавить параметры, взять &lt;code&gt;url.href&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Worker threads в Node.js: параллельные вычисления</title>
      <link>https://hackerx.ru/node-worker-threads/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-worker-threads/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Основной поток Node один&lt;/strong&gt; — тяжёлое вычисление в нём блокирует весь сервер.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Worker threads&lt;/strong&gt; выносят процессорные задачи в отдельные потоки, не мешая &lt;a href=&#34;https://hackerx.ru/node-event-loop/&#34;&gt;event loop&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Только для CPU-задач:&lt;/strong&gt; обработка изображений, шифрование, сложные расчёты. Для &lt;a href=&#34;https://hackerx.ru/node-js-promise/&#34;&gt;ввода-вывода&lt;/a&gt; не нужны.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Отличие от &lt;a href=&#34;https://hackerx.ru/node-cluster/&#34;&gt;cluster&lt;/a&gt;:&lt;/strong&gt; cluster — процессы для распределения запросов, threads — потоки для вычислений.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Обмен данными — сообщениями&lt;/strong&gt; (&lt;code&gt;postMessage&lt;/code&gt;); данные копируются, а не разделяются.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Валидация в Express: проверка входящих данных</title>
      <link>https://hackerx.ru/express-validation/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-validation/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Клиенту доверять нельзя:&lt;/strong&gt; клиентскую валидацию обходят отключением JS или прямым запросом. Серверная — обязательна.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Проверяют по схеме:&lt;/strong&gt; описать ожидаемые данные (&lt;code&gt;Zod&lt;/code&gt;/&lt;code&gt;Joi&lt;/code&gt;) и проверить &lt;code&gt;req.body&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Оформляют как &lt;a href=&#34;https://hackerx.ru/express-middleware/&#34;&gt;middleware&lt;/a&gt;&lt;/strong&gt; — переиспользуемая проверка перед обработчиком.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;При ошибке — 400&lt;/strong&gt; и структурированный список ошибок по полям.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Валидация ≠ вся безопасность:&lt;/strong&gt; от инъекций защищают параметризованные запросы и экранирование.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Дата и время в JavaScript: объект Date без боли</title>
      <link>https://hackerx.ru/js-date/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-date/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;new Date()&lt;/code&gt;&lt;/strong&gt; — текущий момент; &lt;code&gt;Date.now()&lt;/code&gt; — timestamp (миллисекунды с 1970 года).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ловушка: месяцы с нуля&lt;/strong&gt; — январь &lt;code&gt;0&lt;/code&gt;, декабрь &lt;code&gt;11&lt;/code&gt;; а дни месяца с &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Форматирование:&lt;/strong&gt; &lt;code&gt;toLocaleDateString(&#39;ru-RU&#39;)&lt;/code&gt; вместо ручной сборки из частей.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Разница дат:&lt;/strong&gt; &lt;code&gt;date2 - date1&lt;/code&gt; даёт миллисекунды, дальше делят на единицы времени.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для сложных задач&lt;/strong&gt; (таймзоны, парсинг) — библиотека &lt;code&gt;date-fns&lt;/code&gt; или новый &lt;code&gt;Temporal&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Делегирование событий в JavaScript: один обработчик</title>
      <link>https://hackerx.ru/js-event-delegation/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-event-delegation/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Делегирование — один обработчик на родителе&lt;/strong&gt; вместо обработчика на каждом ребёнке.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Работает через &lt;a href=&#34;https://hackerx.ru/js-dom-events/&#34;&gt;всплытие&lt;/a&gt;:&lt;/strong&gt; событие от любого ребёнка доходит до родителя.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;event.target.closest(&#39;.item&#39;)&lt;/code&gt;&lt;/strong&gt; находит нужный элемент, даже если кликнули по вложенному.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ловит динамические элементы&lt;/strong&gt;, добавленные после загрузки — им отдельный обработчик не нужен.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Экономит память&lt;/strong&gt; — вместо сотен слушателей один.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Клик по пункту списка всплывает вверх к единственному обработчику на родительском ul, который ловит все пункты&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · ДЕЛЕГИРОВАНИЕ СОБЫТИЙ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;120&#34; y=&#34;90&#34; width=&#34;620&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;120&#34; y=&#34;90&#34; width=&#34;620&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;150&#34; y=&#34;126&#34; class=&#34;il-lbl&#34;&gt;&amp;lt;ul&amp;gt;&lt;/text&gt;&#xA;  &lt;rect x=&#34;470&#34; y=&#34;104&#34; width=&#34;250&#34; height=&#34;40&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;470&#34; y=&#34;104&#34; width=&#34;250&#34; height=&#34;40&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;595&#34; y=&#34;130&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;1 слушатель&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;160&#34; y=&#34;176&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;160&#34; y=&#34;176&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;185&#34; y=&#34;208&#34; class=&#34;il-mono&#34;&gt;&amp;lt;li&amp;gt; пункт 1&lt;/text&gt;&#xA;  &lt;rect x=&#34;160&#34; y=&#34;240&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;160&#34; y=&#34;240&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;185&#34; y=&#34;272&#34; class=&#34;il-mono&#34;&gt;&amp;lt;li&amp;gt; пункт 2&lt;/text&gt;&#xA;  &lt;circle cx=&#34;640&#34; cy=&#34;266&#34; r=&#34;11&#34; class=&#34;il-accent&#34;/&gt;&#xA;  &lt;text x=&#34;640&#34; y=&#34;271&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34; style=&#34;fill:var(--bg)&#34;&gt;✔&lt;/text&gt;&#xA;  &lt;rect x=&#34;160&#34; y=&#34;304&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;160&#34; y=&#34;304&#34; width=&#34;540&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;185&#34; y=&#34;336&#34; class=&#34;il-mono&#34;&gt;&amp;lt;li&amp;gt; пункт 3 (добавлен позже)&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 595 240 L 595 148&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M595,148 l-6,13 l12,0 z&#34;/&gt;&#xA;  &lt;text x=&#34;760&#34; y=&#34;250&#34; class=&#34;il-sm&#34;&gt;клик по пункту&lt;/text&gt;&#xA;  &lt;text x=&#34;760&#34; y=&#34;190&#34; class=&#34;il-sm&#34;&gt;всплывает вверх…&lt;/text&gt;&#xA;  &lt;text x=&#34;760&#34; y=&#34;130&#34; class=&#34;il-sm&#34;&gt;…и его ловит&lt;/text&gt;&#xA;  &lt;text x=&#34;760&#34; y=&#34;154&#34; class=&#34;il-mono-a&#34;&gt;event.target&lt;/text&gt;&#xA;&#xA;  &lt;text x=&#34;430&#34; y=&#34;380&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;ОДИН ОБРАБОТЧИК ЛОВИТ ВСЕ ПУНКТЫ — ДАЖЕ ДОБАВЛЕННЫЕ ПОЗЖЕ&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Делегирование: один слушатель на родителе ловит клики детей&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Деструктуризация в JavaScript: объекты и массивы</title>
      <link>https://hackerx.ru/js-destructuring/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-destructuring/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Деструктуризация вынимает значения из объекта или массива в переменные одной строкой.&lt;/strong&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Массив — по позиции&lt;/strong&gt; (&lt;code&gt;const [a, b] = arr&lt;/code&gt;), &lt;strong&gt;объект — по имени&lt;/strong&gt; (&lt;code&gt;const { name } = obj&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Значения по умолчанию&lt;/strong&gt; через &lt;code&gt;=&lt;/code&gt;, &lt;strong&gt;переименование&lt;/strong&gt; через &lt;code&gt;:&lt;/code&gt; (только для объектов).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;В параметрах функции&lt;/strong&gt; — удобный способ принять объект-настройки с дефолтами.&lt;/li&gt;&#xA;&lt;li&gt;Внутри — &lt;a href=&#34;https://hackerx.ru/js-spread-rest/&#34;&gt;spread/rest&lt;/a&gt; (&lt;code&gt;...остальное&lt;/code&gt;) собирает то, что не разобрали.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Замыкания в JavaScript: как и зачем</title>
      <link>https://hackerx.ru/js-closures/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-closures/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Замыкание — функция, запомнившая переменные из места, где создана&lt;/strong&gt;, и сохраняющая к ним доступ после завершения внешней функции.&lt;/li&gt;&#xA;&lt;li&gt;Это не отдельная конструкция, а следствие того, как устроена &lt;a href=&#34;https://hackerx.ru/js-scope-hoisting/&#34;&gt;область видимости&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Главное применение — &lt;strong&gt;приватные данные&lt;/strong&gt;: переменную видит только замыкание, снаружи не достать.&lt;/li&gt;&#xA;&lt;li&gt;Классическая ловушка — &lt;strong&gt;&lt;code&gt;var&lt;/code&gt; в цикле&lt;/strong&gt;: все замыкания делят одну переменную. Лечится заменой на &lt;a href=&#34;https://hackerx.ru/js-variables/&#34;&gt;&lt;code&gt;let&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;На замыканиях построены хуки React, счётчики, фабрики функций и половина функционального стиля.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Внешняя функция makeCounter завершилась, но возвращённая внутренняя функция через замыкание держит переменную count живой&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · ЗАМЫКАНИЕ&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;60&#34; y=&#34;90&#34; width=&#34;470&#34; height=&#34;250&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;60&#34; y=&#34;90&#34; width=&#34;470&#34; height=&#34;250&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34; stroke-dasharray=&#34;7 6&#34;/&gt;&#xA;  &lt;text x=&#34;295&#34; y=&#34;126&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;makeCounter()&lt;/text&gt;&#xA;  &lt;text x=&#34;295&#34; y=&#34;148&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;внешняя функция уже завершилась&lt;/text&gt;&#xA;  &lt;rect x=&#34;100&#34; y=&#34;168&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;100&#34; y=&#34;168&#34; width=&#34;200&#34; height=&#34;46&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;200&#34; y=&#34;197&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;count = 0&lt;/text&gt;&#xA;  &lt;rect x=&#34;100&#34; y=&#34;242&#34; width=&#34;390&#34; height=&#34;72&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&#xA;  &lt;rect x=&#34;100&#34; y=&#34;242&#34; width=&#34;390&#34; height=&#34;72&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;295&#34; y=&#34;285&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;return () =&amp;gt; ++count&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 535 210 L 695 210&#34; class=&#34;il-arrow-a&#34;/&gt;&#xA;  &lt;path class=&#34;il-ah-a&#34; d=&#34;M695,210 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;615&#34; y=&#34;197&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;возвращает&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;700&#34; y=&#34;168&#34; width=&#34;440&#34; height=&#34;118&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;700&#34; y=&#34;168&#34; width=&#34;440&#34; height=&#34;118&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;920&#34; y=&#34;204&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;const counter = makeCounter()&lt;/text&gt;&#xA;  &lt;text x=&#34;920&#34; y=&#34;248&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;counter() → 1 → 2 → 3 …&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 200 216 L 200 372 L 920 372 L 920 290&#34; class=&#34;il-accent-line&#34; stroke-dasharray=&#34;7 6&#34; fill=&#34;none&#34;/&gt;&#xA;  &lt;path class=&#34;il-ah-a&#34; d=&#34;M920,290 l-6,-13 l12,0 z&#34;/&gt;&#xA;  &lt;text x=&#34;560&#34; y=&#34;360&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;замыкание держит &lt;tspan class=&#34;il-mono-a&#34;&gt;count&lt;/tspan&gt; живым&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Замыкание: внутренняя функция помнит переменную внешней&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Итераторы и генераторы в JavaScript простыми словами</title>
      <link>https://hackerx.ru/js-iterators-generators/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-iterators-generators/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Итератор — объект с &lt;code&gt;next()&lt;/code&gt;&lt;/strong&gt;, возвращающим &lt;code&gt;{ value, done }&lt;/code&gt;; на нём построен &lt;code&gt;for...of&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Перебираемым&lt;/strong&gt; объект делает метод &lt;a href=&#34;https://hackerx.ru/js-symbol/&#34;&gt;&lt;code&gt;Symbol.iterator&lt;/code&gt;&lt;/a&gt; — он есть у массивов, строк, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Генератор&lt;/strong&gt; (&lt;code&gt;function*&lt;/code&gt;) приостанавливается на &lt;code&gt;yield&lt;/code&gt; и возобновляется — автоматически создаёт итератор.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;yield&lt;/code&gt;&lt;/strong&gt; отдаёт значение и замораживает функцию до следующего &lt;code&gt;next()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Применение:&lt;/strong&gt; ленивые и бесконечные последовательности, вычисляемые по требованию.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Классы в JavaScript: сахар над прототипами</title>
      <link>https://hackerx.ru/js-classes/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-classes/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Класс — синтаксический сахар над &lt;a href=&#34;https://hackerx.ru/js-prototypes/&#34;&gt;прототипами&lt;/a&gt;:&lt;/strong&gt; &lt;code&gt;class&lt;/code&gt; создаёт конструктор и кладёт методы в &lt;code&gt;prototype&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;constructor&lt;/code&gt;&lt;/strong&gt; вызывается при &lt;code&gt;new&lt;/code&gt; и настраивает экземпляр; методы — общие для всех экземпляров.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Наследование:&lt;/strong&gt; &lt;code&gt;extends&lt;/code&gt; + &lt;code&gt;super()&lt;/code&gt; в конструкторе наследника (обязателен до &lt;code&gt;this&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Приватные поля через &lt;code&gt;#&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;#secret&lt;/code&gt; виден только внутри класса — настоящая приватность, а не соглашение.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;static&lt;/code&gt;&lt;/strong&gt; — метод класса, а не экземпляра: &lt;code&gt;Class.method()&lt;/code&gt;. Классы нужны не всегда — для данных хватает объектов.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Логирование в Node.js: от console.log к нормальным логам</title>
      <link>https://hackerx.ru/node-logging/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-logging/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;console.log&lt;/code&gt; не для продакшена:&lt;/strong&gt; без уровней, без структуры, синхронно тормозит под нагрузкой.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Уровни&lt;/strong&gt; (&lt;code&gt;error&lt;/code&gt;/&lt;code&gt;warn&lt;/code&gt;/&lt;code&gt;info&lt;/code&gt;/&lt;code&gt;debug&lt;/code&gt;) фильтруют вывод: в проде только важное, &lt;code&gt;debug&lt;/code&gt; — при отладке.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Структурные JSON-логи&lt;/strong&gt; — искать и агрегировать по полям (&lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;requestId&lt;/code&gt;), а не по тексту.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Библиотеки:&lt;/strong&gt; &lt;code&gt;pino&lt;/code&gt; (самая быстрая) или &lt;code&gt;winston&lt;/code&gt; (гибче).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Нельзя логировать&lt;/strong&gt; пароли, токены, карты, персданные — логи хранятся и агрегируются.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Маршрутизация в Express: пути, параметры, роутеры</title>
      <link>https://hackerx.ru/express-routing/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-routing/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Маршрут = метод HTTP + путь&lt;/strong&gt; → обработчик. Express сопоставляет запрос и вызывает нужную функцию.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Параметры пути&lt;/strong&gt; &lt;code&gt;/users/:id&lt;/code&gt; → &lt;code&gt;req.params&lt;/code&gt;; &lt;strong&gt;строка запроса&lt;/strong&gt; &lt;code&gt;?sort=name&lt;/code&gt; → &lt;code&gt;req.query&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;express.Router&lt;/code&gt;&lt;/strong&gt; разбивает маршруты на модули (пользователи, заказы — в разных файлах).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Порядок важен:&lt;/strong&gt; Express берёт &lt;strong&gt;первый&lt;/strong&gt; совпавший маршрут сверху вниз.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Обработчик 404&lt;/strong&gt; — без пути, в самом конце, ловит всё несовпавшее.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Методы Object: keys, entries, assign, freeze</title>
      <link>https://hackerx.ru/js-object-methods/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-object-methods/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Object.keys / values / entries&lt;/code&gt;&lt;/strong&gt; — перебор: массивы ключей, значений и пар &lt;code&gt;[ключ, значение]&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Object.fromEntries&lt;/code&gt;&lt;/strong&gt; — обратно из пар в объект; вместе с &lt;code&gt;entries&lt;/code&gt; даёт «объект как массив».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Object.assign(target, ...src)&lt;/code&gt;&lt;/strong&gt; — копирует свойства, &lt;strong&gt;мутирует&lt;/strong&gt; цель; чаще берут spread &lt;code&gt;{ ...a }&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Object.freeze&lt;/code&gt;&lt;/strong&gt; — защита от изменений, но &lt;strong&gt;поверхностная&lt;/strong&gt; (только верхний уровень).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;Object.hasOwn(obj, key)&lt;/code&gt;&lt;/strong&gt; — современная проверка собственного свойства вместо &lt;code&gt;hasOwnProperty&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль crypto в Node.js: хеши, соль, шифрование</title>
      <link>https://hackerx.ru/node-crypto/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-crypto/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Хеш необратим&lt;/strong&gt; (проверка паролей, целостность), &lt;strong&gt;шифрование обратимо&lt;/strong&gt; (данные можно расшифровать ключом). Путать нельзя.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Пароли нельзя хешировать через SHA-256&lt;/strong&gt; — он слишком быстрый. Нужны медленные &lt;code&gt;scrypt&lt;/code&gt;, &lt;code&gt;bcrypt&lt;/code&gt;, &lt;code&gt;argon2&lt;/code&gt; с солью.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Соль&lt;/strong&gt; — случайные данные к паролю: делает одинаковые пароли разными и убивает радужные таблицы.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Случайность только через &lt;code&gt;crypto&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;randomBytes&lt;/code&gt;, &lt;code&gt;randomUUID&lt;/code&gt;. &lt;code&gt;Math.random()&lt;/code&gt; для токенов предсказуем и опасен.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;HMAC&lt;/strong&gt; — хеш с секретным ключом: подтверждает и целостность, и подлинность (подпись вебхуков).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль path в Node.js: пути без ошибок на всех ОС</title>
      <link>https://hackerx.ru/node-path/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-path/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Не склеивайте пути строками.&lt;/strong&gt; Разделитель зависит от ОС: &lt;code&gt;path.join(a, b)&lt;/code&gt; подставит правильный, &lt;code&gt;a + &#39;/&#39; + b&lt;/code&gt; сломается на Windows.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;join&lt;/code&gt; соединяет, &lt;code&gt;resolve&lt;/code&gt; строит абсолютный путь&lt;/strong&gt; — и обрывает всё левее абсолютного сегмента.&lt;/li&gt;&#xA;&lt;li&gt;Разбор: &lt;code&gt;basename&lt;/code&gt; (имя), &lt;code&gt;dirname&lt;/code&gt; (каталог), &lt;code&gt;extname&lt;/code&gt; (расширение), &lt;code&gt;parse&lt;/code&gt; (всё сразу).&lt;/li&gt;&#xA;&lt;li&gt;Пути к соседним файлам стройте от &lt;strong&gt;&lt;code&gt;import.meta.dirname&lt;/code&gt;&lt;/strong&gt;, а не от рабочего каталога.&lt;/li&gt;&#xA;&lt;li&gt;Относительные пути считаются от &lt;code&gt;process.cwd()&lt;/code&gt; — отсюда «работает у меня, падает в проде».&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль readline в Node.js: чтение ввода построчно</title>
      <link>https://hackerx.ru/node-readline/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-readline/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;readline&lt;/code&gt; читает данные построчно&lt;/strong&gt; из потока — ввода в консоли или содержимого файла.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ввод пользователя:&lt;/strong&gt; &lt;code&gt;rl.question(...)&lt;/code&gt;; промис-версия &lt;code&gt;node:readline/promises&lt;/code&gt; даёт &lt;code&gt;await rl.question&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Большой файл построчно:&lt;/strong&gt; &lt;a href=&#34;https://hackerx.ru/node-transform-streams/&#34;&gt;поток&lt;/a&gt; + &lt;code&gt;createInterface&lt;/code&gt; + &lt;code&gt;for await&lt;/code&gt; — без загрузки целиком.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Почему не &lt;code&gt;readFile&lt;/code&gt;:&lt;/strong&gt; он грузит файл в память полностью; readline держит одну строку за раз.&lt;/li&gt;&#xA;&lt;li&gt;Незаменим для интерактивных скриптов и обработки гигабайтных логов.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль util в Node.js: промисификация и отладка</title>
      <link>https://hackerx.ru/node-util/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-util/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;util&lt;/code&gt; — набор служебных утилит&lt;/strong&gt; стандартной библиотеки Node.js, без установки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;util.promisify(fn)&lt;/code&gt;&lt;/strong&gt; превращает колбэк-функцию (ошибка первым аргументом) в возвращающую промис — для &lt;a href=&#34;https://hackerx.ru/node-js-promise/&#34;&gt;async/await&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;util.inspect(obj)&lt;/code&gt;&lt;/strong&gt; форматирует объект для отладки глубже, чем &lt;code&gt;console.log&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;util.debuglog(name)&lt;/code&gt;&lt;/strong&gt; — условное логирование по переменной &lt;code&gt;NODE_DEBUG&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Нужен для старых колбэк-API и детальной отладки сложных объектов.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Область видимости и hoisting в JavaScript</title>
      <link>https://hackerx.ru/js-scope-hoisting/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-scope-hoisting/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Область видимости — где переменная доступна.&lt;/strong&gt; Три уровня: глобальная, функции, блока (&lt;code&gt;{}&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;var&lt;/code&gt; виден во всей функции, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; — только в своём блоке.&lt;/strong&gt; Отсюда преимущество &lt;a href=&#34;https://hackerx.ru/js-variables/&#34;&gt;&lt;code&gt;let&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Hoisting:&lt;/strong&gt; &lt;code&gt;var&lt;/code&gt; всплывает со значением &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; — в &lt;strong&gt;мёртвую зону&lt;/strong&gt; (ошибка до объявления).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Область лексическая:&lt;/strong&gt; определяется тем, где функция &lt;em&gt;написана&lt;/em&gt;, а не откуда вызвана. На этом стоят &lt;a href=&#34;https://hackerx.ru/js-closures/&#34;&gt;замыкания&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Переменная ищется по &lt;strong&gt;цепочке областей&lt;/strong&gt; — от своей наружу до глобальной.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Обработка ошибок в Express: middleware ошибок</title>
      <link>https://hackerx.ru/express-error-handling/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/express-error-handling/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Обработчик ошибок — middleware с 4 аргументами&lt;/strong&gt; &lt;code&gt;(err, req, res, next)&lt;/code&gt;; Express узнаёт его по их числу.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ставят в самом конце&lt;/strong&gt;, после всех маршрутов — ловит ошибки со всех в одном месте.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Передача ошибки:&lt;/strong&gt; &lt;code&gt;next(err)&lt;/code&gt; перескакивает к обработчику; синхронный &lt;code&gt;throw&lt;/code&gt; Express ловит сам.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Async-ошибки:&lt;/strong&gt; в Express 4 ловят &lt;code&gt;try/catch&lt;/code&gt; + &lt;code&gt;next(err)&lt;/code&gt;; в Express 5 — автоматически.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Клиенту — общее сообщение&lt;/strong&gt;, полный стек — &lt;a href=&#34;https://hackerx.ru/node-logging/&#34;&gt;в лог&lt;/a&gt;; детали наружу не отдают.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Обработка ошибок в JavaScript: try/catch и throw</title>
      <link>https://hackerx.ru/js-error-handling/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-error-handling/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;try/catch&lt;/code&gt;&lt;/strong&gt; ловит ошибку: код в &lt;code&gt;try&lt;/code&gt; падает — управление уходит в &lt;code&gt;catch&lt;/code&gt; с объектом ошибки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;throw new Error(&#39;текст&#39;)&lt;/code&gt;&lt;/strong&gt; — бросайте объект &lt;code&gt;Error&lt;/code&gt;, не строку: у него есть &lt;code&gt;message&lt;/code&gt; и &lt;code&gt;stack&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;finally&lt;/code&gt;&lt;/strong&gt; выполняется всегда — сюда кладут освобождение ресурсов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;async/await&lt;/code&gt;&lt;/strong&gt; ловят обычным &lt;code&gt;try/catch&lt;/code&gt; вокруг &lt;code&gt;await&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Антипаттерн — пустой &lt;code&gt;catch {}&lt;/code&gt;:&lt;/strong&gt; он прячет баг, а не решает его.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Обработка ошибок в Node.js: не дать серверу упасть</title>
      <link>https://hackerx.ru/node-error-handling/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-error-handling/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;На сервере ставки выше:&lt;/strong&gt; необработанная ошибка роняет процесс и оставляет всех без сервиса.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Операционные ошибки&lt;/strong&gt; (БД недоступна, файла нет) — обрабатывают и продолжают; &lt;strong&gt;баги&lt;/strong&gt; — чинят, не маскируют.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Async:&lt;/strong&gt; &lt;a href=&#34;https://hackerx.ru/js-error-handling/&#34;&gt;&lt;code&gt;try/catch&lt;/code&gt;&lt;/a&gt; вокруг &lt;code&gt;await&lt;/code&gt;; колбэки — проверка &lt;code&gt;err&lt;/code&gt; первым аргументом.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Нельзя глушить &lt;code&gt;uncaughtException&lt;/code&gt;&lt;/strong&gt; — процесс в неопределённом состоянии: залогировать, завершиться, &lt;a href=&#34;https://hackerx.ru/node-graceful-shutdown/&#34;&gt;перезапустить&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;try/catch&lt;/code&gt; — в точках ожидаемых ошибок&lt;/strong&gt;, остальное всплывает к центральному обработчику.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Операционные ошибки обрабатывают и продолжают, программные баги логируют и перезапускают процесс; uncaughtException не глушат&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;NODE.JS · ОБРАБОТКА ОШИБОК&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;80&#34; y=&#34;176&#34; width=&#34;230&#34; height=&#34;100&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;80&#34; y=&#34;176&#34; width=&#34;230&#34; height=&#34;100&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;195&#34; y=&#34;216&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;try { … }&lt;/text&gt;&#xA;  &lt;text x=&#34;195&#34; y=&#34;248&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;возникла ошибка&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 312 226 L 392 226&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M392,226 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;rect x=&#34;400&#34; y=&#34;180&#34; width=&#34;180&#34; height=&#34;92&#34; rx=&#34;12&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;400&#34; y=&#34;180&#34; width=&#34;180&#34; height=&#34;92&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;490&#34; y=&#34;216&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;какой тип?&lt;/text&gt;&#xA;  &lt;text x=&#34;490&#34; y=&#34;246&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;operational или bug&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;700&#34; y=&#34;86&#34; width=&#34;440&#34; height=&#34;112&#34; rx=&#34;12&#34; class=&#34;il-ok-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;700&#34; y=&#34;86&#34; width=&#34;440&#34; height=&#34;112&#34; rx=&#34;12&#34; class=&#34;il-ok-line&#34;/&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;124&#34; class=&#34;il-lbl&#34;&gt;Операционная&lt;/text&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;152&#34; class=&#34;il-sm&#34;&gt;БД недоступна · нет файла · неверный ввод&lt;/text&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;180&#34; class=&#34;il-mono&#34; style=&#34;fill:#1baf7a&#34;&gt;обработать и продолжить&lt;/text&gt;&#xA;  &lt;path d=&#34;M 582 206 L 696 150&#34; class=&#34;il-ok-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M696,150 l-3,13 l12,-6 z&#34; style=&#34;fill:#1baf7a&#34;/&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;700&#34; y=&#34;254&#34; width=&#34;440&#34; height=&#34;112&#34; rx=&#34;12&#34; class=&#34;il-bad-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;700&#34; y=&#34;254&#34; width=&#34;440&#34; height=&#34;112&#34; rx=&#34;12&#34; class=&#34;il-bad-line&#34;/&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;292&#34; class=&#34;il-lbl&#34;&gt;Программный баг&lt;/text&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;320&#34; class=&#34;il-sm&#34;&gt;обращение к undefined · вызов не-функции&lt;/text&gt;&#xA;  &lt;text x=&#34;730&#34; y=&#34;348&#34; class=&#34;il-mono&#34; style=&#34;fill:#e34948&#34;&gt;залогировать → перезапустить&lt;/text&gt;&#xA;  &lt;path d=&#34;M 582 246 L 696 300&#34; class=&#34;il-bad-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M696,300 l-3,-13 l12,6 z&#34; style=&#34;fill:#e34948&#34;/&gt;&#xA;&#xA;  &lt;text x=&#34;490&#34; y=&#34;330&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;не глушить&lt;/text&gt;&#xA;  &lt;text x=&#34;490&#34; y=&#34;352&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;uncaughtException&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Ошибки: операционную обработать, баг — залогировать и перезапустить&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Объекты в JavaScript: создание и работа</title>
      <link>https://hackerx.ru/js-objects/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-objects/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Объект — набор пар ключ-значение.&lt;/strong&gt; Создают литералом &lt;code&gt;{}&lt;/code&gt;, доступ — через точку или квадратные скобки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Точка&lt;/strong&gt; — когда имя известно; &lt;strong&gt;скобки&lt;/strong&gt; — когда имя в переменной или со спецсимволами.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Перебор:&lt;/strong&gt; &lt;code&gt;Object.keys&lt;/code&gt; / &lt;code&gt;values&lt;/code&gt; / &lt;code&gt;entries&lt;/code&gt;. &lt;code&gt;for...in&lt;/code&gt; устарел — обходит и унаследованное.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Копирование:&lt;/strong&gt; &lt;code&gt;{ ...obj }&lt;/code&gt; поверхностное (вложенное общее), &lt;code&gt;structuredClone&lt;/code&gt; — глубокое.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Проверка свойства:&lt;/strong&gt; &lt;code&gt;Object.hasOwn(obj, key)&lt;/code&gt; — надёжнее, чем сравнение с &lt;code&gt;undefined&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Операторы в JavaScript: сравнение, логика, современные</title>
      <link>https://hackerx.ru/js-operators/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-operators/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Всегда &lt;code&gt;===&lt;/code&gt;, не &lt;code&gt;==&lt;/code&gt;:&lt;/strong&gt; строгое сравнение без приведения типов избавляет от сюрпризов вроде &lt;code&gt;0 == &#39;&#39;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; и &lt;code&gt;||&lt;/code&gt; возвращают операнд, а не булево:&lt;/strong&gt; &lt;code&gt;||&lt;/code&gt; — первый истинный, &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; — первый ложный.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;??&lt;/code&gt; (нулевое слияние)&lt;/strong&gt; срабатывает только на &lt;code&gt;null&lt;/code&gt;/&lt;code&gt;undefined&lt;/code&gt; — правильный выбор для дефолтов, где &lt;code&gt;0&lt;/code&gt; валиден.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;?.&lt;/code&gt; (опциональная цепочка)&lt;/strong&gt; безопасно читает вложенные свойства без ошибок.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Тернарный &lt;code&gt;? :&lt;/code&gt;&lt;/strong&gt; — компактный &lt;code&gt;if/else&lt;/code&gt; как выражение.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Отладка Node.js: от console.log до отладчика</title>
      <link>https://hackerx.ru/node-debugging/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-debugging/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Три уровня отладки:&lt;/strong&gt; точечный &lt;code&gt;console.log&lt;/code&gt;, встроенный инспектор (&lt;code&gt;--inspect&lt;/code&gt;), отладчик в редакторе.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;console.log&lt;/code&gt;&lt;/strong&gt; — быстро для простого; на запутанных багах тонет в десятках выводов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;--inspect&lt;/code&gt;&lt;/strong&gt; открывает порт отладки → Chrome DevTools с точками останова и просмотром переменных.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;--inspect-brk&lt;/code&gt;&lt;/strong&gt; останавливает на первой строке (для отладки старта).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;VS Code&lt;/strong&gt; — точки останова кликом, стек и переменные прямо в редакторе.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Переменные в JavaScript: var, let, const</title>
      <link>https://hackerx.ru/js-variables/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-variables/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;По умолчанию &lt;code&gt;const&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt; — если значение меняется, &lt;code&gt;var&lt;/code&gt; — никогда&lt;/strong&gt; в новом коде.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;var&lt;/code&gt; виден во всей функции и &lt;strong&gt;всплывает&lt;/strong&gt; (hoisting); &lt;code&gt;let&lt;/code&gt; и &lt;code&gt;const&lt;/code&gt; живут только в своём блоке &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;const&lt;/code&gt; не делает значение неизменяемым&lt;/strong&gt; — он запрещает переприсвоить переменную. Объект под &lt;code&gt;const&lt;/code&gt; менять можно.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;let&lt;/code&gt; в цикле создаёт &lt;strong&gt;новую переменную на каждой итерации&lt;/strong&gt; — &lt;code&gt;var&lt;/code&gt; создавал одну на всех, отсюда классический баг с колбэками.&lt;/li&gt;&#xA;&lt;li&gt;Переменная без ключевого слова утекает в глобальную область — всегда объявляйте явно.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Переменные окружения в Node.js: конфигурация и секреты</title>
      <link>https://hackerx.ru/node-env-config/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-env-config/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Переменные окружения — конфигурация вне кода:&lt;/strong&gt; порт, адрес БД, ключи API читаются через &lt;code&gt;process.env&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Секреты никогда не в коде и git&lt;/strong&gt; — код виден всем, история хранится вечно. Файл &lt;code&gt;.env&lt;/code&gt; → в &lt;code&gt;.gitignore&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Загрузка &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt; встроенный флаг &lt;code&gt;--env-file=.env&lt;/code&gt; (свежий Node) или пакет &lt;code&gt;dotenv&lt;/code&gt; (старые проекты).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;process.env&lt;/code&gt; — всегда строки:&lt;/strong&gt; порт через &lt;code&gt;Number&lt;/code&gt;, флаги сравнивают со строкой.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;NODE_ENV&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;development&lt;/code&gt;/&lt;code&gt;production&lt;/code&gt;) разделяет поведение и настройки окружений.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Поиск элементов в DOM: querySelector и друзья</title>
      <link>https://hackerx.ru/js-dom-selectors/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-dom-selectors/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;querySelector(sel)&lt;/code&gt;&lt;/strong&gt; — первый элемент по CSS-селектору или &lt;code&gt;null&lt;/code&gt;; &lt;strong&gt;&lt;code&gt;querySelectorAll(sel)&lt;/code&gt;&lt;/strong&gt; — все, в виде &lt;code&gt;NodeList&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CSS-селектор любой:&lt;/strong&gt; &lt;code&gt;&#39;#id&#39;&lt;/code&gt;, &lt;code&gt;&#39;.class&#39;&lt;/code&gt;, &lt;code&gt;&#39;ul li.active&#39;&lt;/code&gt; — как в стилях.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Всегда проверяйте на &lt;code&gt;null&lt;/code&gt;&lt;/strong&gt; — не найден элемент, обращение к его свойству упадёт с ошибкой.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;NodeList&lt;/code&gt; имеет &lt;code&gt;forEach&lt;/code&gt;&lt;/strong&gt;, но для &lt;code&gt;map&lt;/code&gt;/&lt;code&gt;filter&lt;/code&gt; превратите в массив: &lt;code&gt;[...list]&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Поиск внутри элемента:&lt;/strong&gt; &lt;code&gt;el.querySelector(...)&lt;/code&gt; ограничивает область контейнером.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Примитивы и ссылки в JavaScript: копирование</title>
      <link>https://hackerx.ru/js-primitives-references/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-primitives-references/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Примитивы&lt;/strong&gt; (число, строка, boolean) хранят &lt;strong&gt;значение&lt;/strong&gt; — копируются целиком, независимы.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Объекты и массивы&lt;/strong&gt; хранятся &lt;strong&gt;по ссылке&lt;/strong&gt; — переменная держит адрес, не сам объект.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;const copy = obj&lt;/code&gt; копирует ссылку&lt;/strong&gt;, не объект: изменение через &lt;code&gt;copy&lt;/code&gt; видно в &lt;code&gt;obj&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Аргументы всегда по значению&lt;/strong&gt;, но для объектов это значение — ссылка (свойства менять можно, переприсвоить — нет).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;===&lt;/code&gt; сравнивает объекты по ссылке:&lt;/strong&gt; два одинаковых на вид объекта не равны.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Примитив при копировании создаёт независимую копию значения, а объект копирует ссылку — обе переменные указывают на один объект&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · ЗНАЧЕНИЕ И ССЫЛКА&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;46&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;46&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;311&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Примитив — копия значения&lt;/text&gt;&#xA;  &lt;text x=&#34;311&#34; y=&#34;150&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;let a = 10;  let b = a;&lt;/text&gt;&#xA;  &#xA;  &lt;rect x=&#34;110&#34; y=&#34;196&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;110&#34; y=&#34;196&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;155&#34; y=&#34;233&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;a&lt;/text&gt;&#xA;  &lt;rect x=&#34;250&#34; y=&#34;196&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;250&#34; y=&#34;196&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;295&#34; y=&#34;233&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;10&lt;/text&gt;&#xA;  &lt;path d=&#34;M 202 226 L 246 226&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M246,226 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &#xA;  &lt;rect x=&#34;110&#34; y=&#34;288&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;110&#34; y=&#34;288&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;155&#34; y=&#34;325&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;b&lt;/text&gt;&#xA;  &lt;rect x=&#34;250&#34; y=&#34;288&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;250&#34; y=&#34;288&#34; width=&#34;90&#34; height=&#34;60&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;295&#34; y=&#34;325&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;10&lt;/text&gt;&#xA;  &lt;path d=&#34;M 202 318 L 246 318&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M246,318 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;450&#34; y=&#34;262&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;две&lt;/text&gt;&#xA;  &lt;text x=&#34;450&#34; y=&#34;284&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;независимые&lt;/text&gt;&#xA;  &lt;text x=&#34;450&#34; y=&#34;306&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;копии&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;624&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;624&#34; y=&#34;80&#34; width=&#34;530&#34; height=&#34;300&#34; rx=&#34;14&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;889&#34; y=&#34;118&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Объект — копия ссылки&lt;/text&gt;&#xA;  &lt;text x=&#34;889&#34; y=&#34;150&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;const copy = obj;&lt;/text&gt;&#xA;  &#xA;  &lt;rect x=&#34;668&#34; y=&#34;196&#34; width=&#34;120&#34; height=&#34;56&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;668&#34; y=&#34;196&#34; width=&#34;120&#34; height=&#34;56&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;728&#34; y=&#34;230&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;obj&lt;/text&gt;&#xA;  &lt;rect x=&#34;668&#34; y=&#34;292&#34; width=&#34;120&#34; height=&#34;56&#34; rx=&#34;8&#34; class=&#34;il-panel-2&#34;/&gt;&lt;rect x=&#34;668&#34; y=&#34;292&#34; width=&#34;120&#34; height=&#34;56&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;728&#34; y=&#34;326&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;copy&lt;/text&gt;&#xA;  &#xA;  &lt;rect x=&#34;950&#34; y=&#34;222&#34; width=&#34;170&#34; height=&#34;100&#34; rx=&#34;10&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;950&#34; y=&#34;222&#34; width=&#34;170&#34; height=&#34;100&#34; rx=&#34;10&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;1035&#34; y=&#34;268&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;{ name }&lt;/text&gt;&#xA;  &lt;text x=&#34;1035&#34; y=&#34;298&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;один объект&lt;/text&gt;&#xA;  &lt;path d=&#34;M 790 224 L 946 262&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M946,262 l-14,-1 l7,11 z&#34;/&gt;&#xA;  &lt;path d=&#34;M 790 320 L 946 282&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M946,282 l-7,-12 l14,-1 z&#34;/&gt;&#xA;  &lt;text x=&#34;820&#34; y=&#34;360&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;меняешь через copy — меняется obj&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Примитив копирует значение, объект — ссылку&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Прототипы в JavaScript: наследование под капотом</title>
      <link>https://hackerx.ru/js-prototypes/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-prototypes/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Прототип — объект, у которого другой объект заимствует свойства.&lt;/strong&gt; Нет свойства у себя — ищется в прототипе, дальше по цепочке.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Цепочка прототипов:&lt;/strong&gt; объект → его прототип → прототип прототипа → &amp;hellip; → &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;prototype&lt;/code&gt;&lt;/strong&gt; — свойство конструктора (будущий прототип экземпляров); &lt;strong&gt;&lt;code&gt;__proto__&lt;/code&gt;&lt;/strong&gt; — ссылка объекта на свой прототип.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Классы — сахар над прототипами:&lt;/strong&gt; &lt;code&gt;class&lt;/code&gt; создаёт конструктор и кладёт методы в &lt;code&gt;prototype&lt;/code&gt;, нового механизма нет.&lt;/li&gt;&#xA;&lt;li&gt;Методы в прототипе &lt;strong&gt;общие для всех экземпляров&lt;/strong&gt; — не копируются в каждый.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Цепочка прототипов: объект dog, его прототип animal, затем Object.prototype и null; свойство ищется по цепочке вверх&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · ЦЕПОЧКА ПРОТОТИПОВ&lt;/text&gt;&#xA;  &lt;text x=&#34;600&#34; y=&#34;92&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;Нет свойства у себя — ищем в прототипе, дальше по цепочке, пока не найдём или не дойдём до null&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;46&#34; y=&#34;150&#34; width=&#34;236&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;46&#34; y=&#34;150&#34; width=&#34;236&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;164&#34; y=&#34;184&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;dog&lt;/text&gt;&#xA;  &lt;text x=&#34;164&#34; y=&#34;216&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;{ bark }&lt;/text&gt;&#xA;  &lt;text x=&#34;164&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;сам объект&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;350&#34; y=&#34;150&#34; width=&#34;236&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-accent-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;350&#34; y=&#34;150&#34; width=&#34;236&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-accent-line&#34;/&gt;&#xA;  &lt;text x=&#34;468&#34; y=&#34;184&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;animal&lt;/text&gt;&#xA;  &lt;text x=&#34;468&#34; y=&#34;216&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;{ eat }&lt;/text&gt;&#xA;  &lt;text x=&#34;468&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;dog.eat() найден здесь ✓&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;654&#34; y=&#34;150&#34; width=&#34;300&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;654&#34; y=&#34;150&#34; width=&#34;300&#34; height=&#34;150&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;804&#34; y=&#34;184&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;Object.prototype&lt;/text&gt;&#xA;  &lt;text x=&#34;804&#34; y=&#34;216&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;{ toString, … }&lt;/text&gt;&#xA;  &lt;text x=&#34;804&#34; y=&#34;278&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;общий предок&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;1022&#34; y=&#34;182&#34; width=&#34;132&#34; height=&#34;86&#34; rx=&#34;12&#34; class=&#34;il-panel-2&#34;/&gt;&#xA;  &lt;rect x=&#34;1022&#34; y=&#34;182&#34; width=&#34;132&#34; height=&#34;86&#34; rx=&#34;12&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;1088&#34; y=&#34;232&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34;&gt;null&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 286 225 L 346 225&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M346,225 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;316&#34; y=&#34;212&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;__proto__&lt;/text&gt;&#xA;  &lt;path d=&#34;M 590 225 L 650 225&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M650,225 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;620&#34; y=&#34;212&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;__proto__&lt;/text&gt;&#xA;  &lt;path d=&#34;M 958 225 L 1018 225&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M1018,225 l-13,-6 l0,12 z&#34;/&gt;&#xA;  &lt;text x=&#34;988&#34; y=&#34;212&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;__proto__&lt;/text&gt;&#xA;&#xA;  &lt;text x=&#34;600&#34; y=&#34;356&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;Классы — синтаксический сахар над этой же цепочкой&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Цепочка прототипов: поиск свойства идёт вверх до null&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Работа с папками в Node.js: mkdir, readdir, rm</title>
      <link>https://hackerx.ru/node-fs-directories/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-fs-directories/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Создать вложенные папки&lt;/strong&gt; — &lt;code&gt;mkdir(dir, { recursive: true })&lt;/code&gt;: строит всю цепочку и не падает, если уже есть.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Прочитать содержимое&lt;/strong&gt; — &lt;code&gt;readdir(dir, { withFileTypes: true })&lt;/code&gt;: сразу знаешь, где файл, где папка, без лишних &lt;code&gt;stat&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Удалить с содержимым&lt;/strong&gt; — &lt;code&gt;rm(dir, { recursive: true, force: true })&lt;/code&gt;: замена &lt;code&gt;rmdir&lt;/code&gt; и пакета &lt;code&gt;rimraf&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Обойти дерево&lt;/strong&gt; — &lt;code&gt;readdir(dir, { recursive: true })&lt;/code&gt; одним вызовом (Node 18.17+).&lt;/li&gt;&#xA;&lt;li&gt;Пакеты &lt;code&gt;mkdirp&lt;/code&gt; и &lt;code&gt;rimraf&lt;/code&gt; в новом коде &lt;strong&gt;не нужны&lt;/strong&gt; — всё встроено.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Регулярные выражения в JavaScript: практический старт</title>
      <link>https://hackerx.ru/js-regexp/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-regexp/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Регулярка — шаблон для поиска в тексте.&lt;/strong&gt; &lt;code&gt;test&lt;/code&gt; даёт &lt;code&gt;true&lt;/code&gt;/&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;match&lt;/code&gt; извлекает, &lt;code&gt;replace&lt;/code&gt; заменяет.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Флаги:&lt;/strong&gt; &lt;code&gt;g&lt;/code&gt; — все совпадения, &lt;code&gt;i&lt;/code&gt; — без учёта регистра, &lt;code&gt;m&lt;/code&gt; — многострочный.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Группы захвата&lt;/strong&gt; &lt;code&gt;( )&lt;/code&gt; вытаскивают части; именованные &lt;code&gt;(?&amp;lt;name&amp;gt;...)&lt;/code&gt; — доступ по имени.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;matchAll&lt;/code&gt; + &lt;code&gt;for...of&lt;/code&gt;&lt;/strong&gt; — все совпадения с группами; &lt;code&gt;match&lt;/code&gt; с &lt;code&gt;g&lt;/code&gt; теряет группы.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Не парсите регуляркой HTML/JSON&lt;/strong&gt; — для вложенных структур нужен настоящий парсер.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Рекурсия в JavaScript: когда функция вызывает себя</title>
      <link>https://hackerx.ru/js-recursion/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-recursion/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Рекурсия — функция вызывает саму себя&lt;/strong&gt;, решая задачу через её меньшие версии.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Два обязательных элемента:&lt;/strong&gt; базовый случай (стоп) и шаг (сведение к проще).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Забыть базовый случай = переполнение стека&lt;/strong&gt; (&lt;code&gt;Maximum call stack size exceeded&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Сильна на вложенных структурах&lt;/strong&gt; неизвестной глубины: деревья, файлы, вложенные объекты.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для линейных задач цикл проще и безопаснее&lt;/strong&gt; — рекурсию берут ради читаемости.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Вызовы factorial уходят вглубь до базового случая factorial(1), затем результаты собираются обратно вверх до 24&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;JAVASCRIPT · РЕКУРСИЯ · factorial(4)&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;text x=&#34;150&#34; y=&#34;96&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;вызовы вглубь →&lt;/text&gt;&#xA;  &lt;text x=&#34;1050&#34; y=&#34;96&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;← сборка результата&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;90&#34; y=&#34;120&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;90&#34; y=&#34;120&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;110&#34; y=&#34;152&#34; class=&#34;il-mono&#34;&gt;factorial(4)  = 4 * factorial(3)&lt;/text&gt;&#xA;  &lt;rect x=&#34;130&#34; y=&#34;182&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;130&#34; y=&#34;182&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;150&#34; y=&#34;214&#34; class=&#34;il-mono&#34;&gt;factorial(3)  = 3 * factorial(2)&lt;/text&gt;&#xA;  &lt;rect x=&#34;170&#34; y=&#34;244&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-panel&#34;/&gt;&lt;rect x=&#34;170&#34; y=&#34;244&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-stroke&#34;/&gt;&lt;text x=&#34;190&#34; y=&#34;276&#34; class=&#34;il-mono&#34;&gt;factorial(2)  = 2 * factorial(1)&lt;/text&gt;&#xA;  &lt;rect x=&#34;210&#34; y=&#34;306&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-warn-soft&#34;/&gt;&lt;rect x=&#34;210&#34; y=&#34;306&#34; width=&#34;360&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-warn-line&#34;/&gt;&lt;text x=&#34;230&#34; y=&#34;338&#34; class=&#34;il-mono&#34; style=&#34;fill:#eda100&#34;&gt;factorial(1)  → 1   базовый случай&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;720&#34; y=&#34;306&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;720&#34; y=&#34;306&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;795&#34; y=&#34;338&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;1&lt;/text&gt;&#xA;  &lt;rect x=&#34;720&#34; y=&#34;244&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;720&#34; y=&#34;244&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;795&#34; y=&#34;276&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;2·1 = 2&lt;/text&gt;&#xA;  &lt;rect x=&#34;720&#34; y=&#34;182&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;720&#34; y=&#34;182&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;795&#34; y=&#34;214&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;3·2 = 6&lt;/text&gt;&#xA;  &lt;rect x=&#34;720&#34; y=&#34;120&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-soft&#34;/&gt;&lt;rect x=&#34;720&#34; y=&#34;120&#34; width=&#34;150&#34; height=&#34;52&#34; rx=&#34;8&#34; class=&#34;il-accent-line&#34;/&gt;&lt;text x=&#34;795&#34; y=&#34;152&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono-a&#34;&gt;4·6 = 24&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 60 132 L 60 332&#34; class=&#34;il-arrow&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M60,332 l-6,-13 l12,0 z&#34;/&gt;&#xA;  &#xA;  &lt;path d=&#34;M 900 332 L 900 146&#34; class=&#34;il-arrow-a&#34;/&gt;&lt;path class=&#34;il-ah-a&#34; d=&#34;M900,146 l-6,13 l12,0 z&#34;/&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 574 332 L 716 332&#34; class=&#34;il-warn-line&#34; stroke-dasharray=&#34;6 5&#34; fill=&#34;none&#34;/&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;200&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;без базового&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;222&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;случая —&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;244&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;переполнение&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;266&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;стека&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Рекурсия: стек растёт до базового случая, потом сворачивается&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Сборка мусора в JavaScript: как управляется память</title>
      <link>https://hackerx.ru/js-garbage-collection/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-garbage-collection/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Память освобождается автоматически&lt;/strong&gt; — движок удаляет объекты, до которых нельзя добраться из корней.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Достижимость:&lt;/strong&gt; объект жив, пока есть цепочка ссылок от корней (глобальные, стек вызовов).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Утечки&lt;/strong&gt; = случайно сохранённые ссылки: забытый &lt;code&gt;setInterval&lt;/code&gt;, не снятый &lt;a href=&#34;https://hackerx.ru/js-dom-events/&#34;&gt;слушатель&lt;/a&gt;, растущая коллекция, замыкание.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Лечение:&lt;/strong&gt; &lt;code&gt;clearInterval&lt;/code&gt;, &lt;code&gt;removeEventListener&lt;/code&gt;, очистка коллекций, обнуление ссылок.&lt;/li&gt;&#xA;&lt;li&gt;Задача разработчика — &lt;strong&gt;не мешать сборщику&lt;/strong&gt;, не держать лишнее.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>События в JavaScript: addEventListener на практике</title>
      <link>https://hackerx.ru/js-dom-events/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-dom-events/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;addEventListener(type, handler)&lt;/code&gt;&lt;/strong&gt; вместо &lt;code&gt;onclick&lt;/code&gt;: несколько обработчиков, опции, снятие.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Объект &lt;code&gt;event&lt;/code&gt;&lt;/strong&gt; — аргумент обработчика: &lt;code&gt;event.target&lt;/code&gt; (источник), тип, координаты, клавиша.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;event.preventDefault()&lt;/code&gt;&lt;/strong&gt; отменяет действие браузера (отправку формы, переход по ссылке).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Всплытие:&lt;/strong&gt; событие поднимается от элемента вверх по родителям — основа &lt;a href=&#34;https://hackerx.ru/js-event-delegation/&#34;&gt;делегирования&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Снятие:&lt;/strong&gt; &lt;code&gt;removeEventListener&lt;/code&gt; с той же (именованной) функцией; или опция &lt;code&gt;once&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Создание и изменение элементов DOM в JavaScript</title>
      <link>https://hackerx.ru/js-dom-create/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-dom-create/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;createElement&lt;/code&gt; → настроить → &lt;code&gt;append&lt;/code&gt;:&lt;/strong&gt; элемент создаётся в памяти, потом вставляется в страницу.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;textContent&lt;/code&gt; для текста&lt;/strong&gt; (безопасно), &lt;strong&gt;&lt;code&gt;innerHTML&lt;/code&gt; только для доверенного HTML&lt;/strong&gt; — иначе XSS.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Никогда не кладите данные пользователя в &lt;code&gt;innerHTML&lt;/code&gt;&lt;/strong&gt; — внедрят скрипт.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Много элементов&lt;/strong&gt; вставляйте пакетом (&lt;code&gt;DocumentFragment&lt;/code&gt; или массив в &lt;code&gt;append&lt;/code&gt;), не по одному в цикле.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;el.remove()&lt;/code&gt;&lt;/strong&gt; удаляет элемент; &lt;code&gt;classList&lt;/code&gt;/&lt;code&gt;setAttribute&lt;/code&gt; меняют существующий.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Строки в JavaScript: методы и шаблонные литералы</title>
      <link>https://hackerx.ru/js-strings/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-strings/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Шаблонные литералы&lt;/strong&gt; (обратные кавычки) — подстановка &lt;code&gt;${...}&lt;/code&gt; и многострочность, вместо &lt;code&gt;+&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;slice&lt;/code&gt;&lt;/strong&gt; для вырезания — понимает отрицательные индексы (&lt;code&gt;slice(-3)&lt;/code&gt;); &lt;code&gt;substring&lt;/code&gt; их не понимает.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;includes&lt;/code&gt; / &lt;code&gt;startsWith&lt;/code&gt; / &lt;code&gt;endsWith&lt;/code&gt;&lt;/strong&gt; — проверка вхождения; &lt;code&gt;replaceAll&lt;/code&gt; заменяет все, &lt;code&gt;replace&lt;/code&gt; — только первое.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Строки неизменяемы:&lt;/strong&gt; методы возвращают новую строку, исходную не меняют.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;split&lt;/code&gt; / &lt;code&gt;join&lt;/code&gt;, &lt;code&gt;trim&lt;/code&gt;, &lt;code&gt;padStart&lt;/code&gt;&lt;/strong&gt; — разбор, очистка, форматирование.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Таймеры в Node.js: setTimeout, setInterval, setImmediate</title>
      <link>https://hackerx.ru/node-timers/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-timers/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;setTimeout(fn, ms)&lt;/code&gt; — задержка-минимум, не гарантия.&lt;/strong&gt; Колбэк не выполнится раньше &lt;code&gt;ms&lt;/code&gt;, но может позже, если цикл занят.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;setImmediate&lt;/code&gt; ≠ &lt;code&gt;setTimeout(0)&lt;/code&gt;:&lt;/strong&gt; первый в фазе check, второй в фазе timers. Внутри ввода-вывода &lt;code&gt;setImmediate&lt;/code&gt; всегда раньше.&lt;/li&gt;&#xA;&lt;li&gt;Таймер возвращает &lt;strong&gt;объект &lt;code&gt;Timeout&lt;/code&gt;&lt;/strong&gt;, а не число. У него есть &lt;code&gt;unref()&lt;/code&gt; — «не держать процесс живым ради меня».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Забытый &lt;code&gt;setInterval&lt;/code&gt; — причина №1, почему скрипт не завершается сам.&lt;/strong&gt; Снимайте через &lt;code&gt;clearInterval&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Для пауз в async-коде есть &lt;strong&gt;&lt;code&gt;node:timers/promises&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;await setTimeout(1000)&lt;/code&gt; вместо обёртки в промис.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов с бейджем&lt;/a&gt;. Код дан по документации Node.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Типы данных в JavaScript: примитивы и объекты</title>
      <link>https://hackerx.ru/js-data-types/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-data-types/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Восемь типов:&lt;/strong&gt; семь примитивов (&lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;symbol&lt;/code&gt;, &lt;code&gt;bigint&lt;/code&gt;) и &lt;code&gt;object&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Массивы, функции, даты — это объекты&lt;/strong&gt;, просто разного вида.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;typeof null === &#39;object&#39;&lt;/code&gt;&lt;/strong&gt; — историческая ошибка языка; null проверяют через &lt;code&gt;=== null&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;undefined&lt;/code&gt; — «значение не задано» (обычно от языка), &lt;code&gt;null&lt;/code&gt; — намеренное «пусто» (от вас).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Массив от объекта отличают через &lt;code&gt;Array.isArray()&lt;/code&gt;&lt;/strong&gt; — &lt;code&gt;typeof&lt;/code&gt; для обоих даёт &lt;code&gt;&#39;object&#39;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Управление памятью в Node.js: куча, утечки, профилирование</title>
      <link>https://hackerx.ru/node-memory-management/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-memory-management/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Память процесса меряют через &lt;code&gt;process.memoryUsage()&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;rss&lt;/code&gt; (весь процесс), &lt;code&gt;heapUsed&lt;/code&gt; (объекты в куче).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Куча V8 не бесконечна&lt;/strong&gt; — лимит меняют флагом &lt;code&gt;--max-old-space-size=МБ&lt;/code&gt;; упор в лимит = падение.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Утечки&lt;/strong&gt; — удержанные ссылки: растущие коллекции, незакрытые &lt;a href=&#34;https://hackerx.ru/js-garbage-collection/&#34;&gt;таймеры/слушатели&lt;/a&gt;, кэш без предела.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Поиск:&lt;/strong&gt; два heap snapshot под нагрузкой → сравнить, что выросло.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Большие данные — через &lt;a href=&#34;https://hackerx.ru/node-transform-streams/&#34;&gt;потоки&lt;/a&gt;&lt;/strong&gt;, а не загрузкой в память целиком.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в этой сессии (по договорённости — &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;фокус на контенте&lt;/a&gt;, а не прогонах). Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Формы и валидация в JavaScript: обработка ввода</title>
      <link>https://hackerx.ru/js-forms-validation/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-forms-validation/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Перехват отправки:&lt;/strong&gt; обработчик &lt;code&gt;submit&lt;/code&gt; + &lt;a href=&#34;https://hackerx.ru/js-dom-events/&#34;&gt;&lt;code&gt;event.preventDefault()&lt;/code&gt;&lt;/a&gt; вместо перезагрузки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Чтение полей:&lt;/strong&gt; &lt;code&gt;new FormData(form)&lt;/code&gt; → &lt;a href=&#34;https://hackerx.ru/js-object-methods/&#34;&gt;&lt;code&gt;Object.fromEntries&lt;/code&gt;&lt;/a&gt; даёт объект.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;HTML5-валидация&lt;/strong&gt; (&lt;code&gt;required&lt;/code&gt;, &lt;code&gt;type=&amp;quot;email&amp;quot;&lt;/code&gt;, &lt;code&gt;pattern&lt;/code&gt;) — браузер проверяет сам, JS читает результат.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Клиентская валидация — для удобства, серверная — для безопасности.&lt;/strong&gt; Нужны обе.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Показ ошибок:&lt;/strong&gt; текст в элемент рядом с полем через &lt;code&gt;textContent&lt;/code&gt; + класс.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Функции в JavaScript: объявление, выражение, стрелки</title>
      <link>https://hackerx.ru/js-functions/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-functions/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Объявление&lt;/strong&gt; (&lt;code&gt;function foo(){}&lt;/code&gt;) всплывает — вызывается до объявления. &lt;strong&gt;Выражение&lt;/strong&gt; (&lt;code&gt;const foo = ...&lt;/code&gt;) — нет.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Стрелка — для колбэков&lt;/strong&gt; (берёт &lt;code&gt;this&lt;/code&gt; из окружения), &lt;strong&gt;обычная — для методов&lt;/strong&gt; (свой &lt;code&gt;this&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Параметры по умолчанию&lt;/strong&gt; (&lt;code&gt;name = &#39;гость&#39;&lt;/code&gt;) заменили ломкий приём &lt;code&gt;name || &#39;гость&#39;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;rest&lt;/strong&gt; (&lt;code&gt;...args&lt;/code&gt;) — настоящий массив, в отличие от псевдомассива &lt;code&gt;arguments&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Функция — это объект первого класса:&lt;/strong&gt; её передают, возвращают, кладут в массив. На этом стоят колбэки.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Числа и Math в JavaScript: округление и точность</title>
      <link>https://hackerx.ru/js-numbers-math/</link>
      <pubDate>Fri, 17 Jul 2026 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-numbers-math/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;0.1 + 0.2 !== 0.3&lt;/code&gt;&lt;/strong&gt; — двоичная плавающая точка (IEEE 754), не баг; так во всех языках.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Округление:&lt;/strong&gt; &lt;code&gt;Math.round&lt;/code&gt; (к ближайшему), &lt;code&gt;Math.floor&lt;/code&gt; (вниз), &lt;code&gt;Math.ceil&lt;/code&gt; (вверх), &lt;code&gt;toFixed(n)&lt;/code&gt; — но возвращает &lt;strong&gt;строку&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Парсинг:&lt;/strong&gt; &lt;code&gt;Number&lt;/code&gt; строгий (&lt;code&gt;&#39;12px&#39;&lt;/code&gt; → &lt;code&gt;NaN&lt;/code&gt;), &lt;code&gt;parseInt&lt;/code&gt; терпимый (&lt;code&gt;&#39;12px&#39;&lt;/code&gt; → &lt;code&gt;12&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Проверка:&lt;/strong&gt; &lt;code&gt;Number.isNaN(x)&lt;/code&gt; — надёжно; &lt;code&gt;x === NaN&lt;/code&gt; не работает (NaN не равен себе).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Деньги считают в копейках целыми числами&lt;/strong&gt;, не в рублях с дробью.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль os в Node.js: информация о системе и железе</title>
      <link>https://hackerx.ru/node-js-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C-os-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D0%BE%D0%B9-%D1%81%D0%B8%D1%81%D1%82%D0%B5/</link>
      <pubDate>Sun, 08 Jul 2018 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-%D0%BC%D0%BE%D0%B4%D1%83%D0%BB%D1%8C-os-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0-%D1%81-%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D0%BE%D0%BD%D0%BD%D0%BE%D0%B9-%D1%81%D0%B8%D1%81%D1%82%D0%B5/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;node:os&lt;/code&gt; отвечает на вопрос «где я выполняюсь»: платформа, число ядер, память, домашний каталог, временная папка.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;os.cpus().length&lt;/code&gt; — не то число, которое вам нужно.&lt;/strong&gt; Оно про ядра машины. Сколько ядер реально доступно процессу, показывает &lt;code&gt;os.availableParallelism()&lt;/code&gt; — и в контейнере с лимитом CPU эти числа расходятся.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;os.EOL&lt;/code&gt; — разделитель строк текущей системы: &lt;code&gt;\r\n&lt;/code&gt; на Windows, &lt;code&gt;\n&lt;/code&gt; на Unix. Забыть про него — классическая причина «в git поехал весь файл».&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;os.freemem()&lt;/code&gt; на Linux почти всегда мал: свободную память система держит под дисковым кэшем. Это норма.&lt;/li&gt;&#xA;&lt;li&gt;Про &lt;strong&gt;процесс&lt;/strong&gt; (аргументы, окружение, память самого Node) — &lt;a href=&#34;https://hackerx.ru/node-js-process/&#34;&gt;отдельный модуль&lt;/a&gt;. &lt;code&gt;os&lt;/code&gt; — про машину.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Модуль &lt;code&gt;os&lt;/code&gt; — тонкая прослойка между Node и операционной системой. Он не делает ничего сам, только отвечает на вопросы: сколько ядер, сколько памяти, какая платформа, где домашний каталог. Ставить его не нужно — он встроен.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Потоки в Node.js: Stream, pipeline и почему не readFile</title>
      <link>https://hackerx.ru/node-js-stream-pipe/</link>
      <pubDate>Sun, 08 Jul 2018 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-stream-pipe/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Поток обрабатывает данные &lt;strong&gt;кусками, а не целиком&lt;/strong&gt;: в нашем замере файл на 183 МБ читался порциями максимум по 64 КБ — 2930 кусков.&lt;/li&gt;&#xA;&lt;li&gt;Тот же файл через &lt;code&gt;readFile&lt;/code&gt; дал &lt;strong&gt;+169 МБ к памяти процесса&lt;/strong&gt;: он материализует всё содержимое одним значением.&lt;/li&gt;&#xA;&lt;li&gt;Используйте &lt;code&gt;pipeline&lt;/code&gt;, а не &lt;code&gt;pipe&lt;/code&gt;: &lt;code&gt;pipe&lt;/code&gt; не пробрасывает ошибки и оставляет потоки открытыми при сбое.&lt;/li&gt;&#xA;&lt;li&gt;Лучшая версия — &lt;code&gt;pipeline&lt;/code&gt; из &lt;code&gt;node:stream/promises&lt;/code&gt;: работает с &lt;code&gt;await&lt;/code&gt; и обычным &lt;code&gt;try/catch&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Поток нужен не всегда. Файл на пару мегабайт проще прочитать &lt;code&gt;readFile&lt;/code&gt; — код короче, а разницы не будет.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Потоки — та часть Node, которую чаще всего обходят стороной: &lt;a href=&#34;https://hackerx.ru/fs-readfile-and-fs-readfilesync/&#34;&gt;&lt;code&gt;readFile&lt;/code&gt;&lt;/a&gt; короче и понятнее. Пока файлы маленькие, это и правда так. Проблема появляется, когда «маленький файл» однажды оказывается на 2 ГБ, а процесс падает с &lt;code&gt;out of memory&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Сжатие данных в Node.js: zlib, gzip и brotli</title>
      <link>https://hackerx.ru/node-data-compression-library-zlib/</link>
      <pubDate>Sun, 08 Jul 2018 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-data-compression-library-zlib/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;В Node сжатие встроено: модуль &lt;code&gt;node:zlib&lt;/code&gt; даёт gzip, deflate и brotli, ставить ничего не нужно.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Brotli жмёт лучше gzip, но по умолчанию — в 8 раз медленнее.&lt;/strong&gt; На нашем замере реальной статьи: gzip 6903 байта за 2.5 мс, brotli 5909 байт за 19.5 мс. Выигрыш в размере — 14.4%.&lt;/li&gt;&#xA;&lt;li&gt;Причина в том, что &lt;strong&gt;у brotli качество по умолчанию максимальное (11)&lt;/strong&gt;. С качеством 4 он жмёт за 0.9 мс — быстрее gzip, но и хуже него.&lt;/li&gt;&#xA;&lt;li&gt;На маленьких данных сжатие &lt;strong&gt;вредит&lt;/strong&gt;: 2 байта после gzip превратились в 22.&lt;/li&gt;&#xA;&lt;li&gt;Работайте через &lt;code&gt;pipeline&lt;/code&gt;, а не &lt;code&gt;pipe&lt;/code&gt;: он закроет потоки при ошибке.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Сжатие в Node не требует зависимостей: модуль &lt;code&gt;node:zlib&lt;/code&gt; встроен в платформу и умеет три формата. Вопрос не в том, как вызвать функцию, — вопрос в том, какой формат выбрать и какой ценой.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Webpack в 2026: зачем нужен бандлер и что вместо него</title>
      <link>https://hackerx.ru/webpack-and-nodejs/</link>
      <pubDate>Fri, 06 Jul 2018 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/webpack-and-nodejs/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Бандлер собирает много файлов в оптимизированные бандлы&lt;/strong&gt;, превращает свежий синтаксис в понятный браузерам и импортирует стили, картинки, шрифты как модули.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Webpack жив, но новые проекты начинают на Vite:&lt;/strong&gt; он запускается мгновенно и настраивается проще.&lt;/li&gt;&#xA;&lt;li&gt;Скорость Vite — от &lt;strong&gt;esbuild на Go&lt;/strong&gt;: тяжёлая работа идёт не в JavaScript, как &lt;a href=&#34;https://hackerx.ru/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-node-js/&#34;&gt;и в других инструментах&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Бандлер нужен не всегда:&lt;/strong&gt; браузеры понимают &lt;a href=&#34;https://hackerx.ru/ecmascript6/&#34;&gt;ES-модули&lt;/a&gt; нативно, и небольшому сайту сборка не обязательна.&lt;/li&gt;&#xA;&lt;li&gt;Правило то же, что везде: инструмент берут под задачу, а не по привычке.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Конфиги не собирались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Даны по документации Webpack и Vite. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Глобальные объекты Node.js: globalThis, Buffer, таймеры</title>
      <link>https://hackerx.ru/node-global-objects/</link>
      <pubDate>Fri, 20 Apr 2018 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-global-objects/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Глобальные объекты доступны без импорта. Правильное имя контейнера — &lt;code&gt;globalThis&lt;/code&gt;, а не &lt;code&gt;global&lt;/code&gt;: оно работает и в Node, и в браузере.&lt;/li&gt;&#xA;&lt;li&gt;Без импорта уже есть &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;URL&lt;/code&gt;, &lt;code&gt;AbortController&lt;/code&gt;, &lt;code&gt;structuredClone&lt;/code&gt;, &lt;code&gt;TextEncoder&lt;/code&gt;, &lt;code&gt;Buffer&lt;/code&gt; и таймеры — внешние пакеты для этого больше не нужны.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;structuredClone&lt;/code&gt; делает глубокую копию и &lt;strong&gt;сохраняет &lt;code&gt;Date&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;&lt;/strong&gt; — в отличие от трюка &lt;code&gt;JSON.parse(JSON.stringify(...))&lt;/code&gt;, который их ломает.&lt;/li&gt;&#xA;&lt;li&gt;Порядок: синхронный код → &lt;code&gt;nextTick&lt;/code&gt; → микрозадачи → &lt;code&gt;setImmediate&lt;/code&gt; → &lt;code&gt;setTimeout&lt;/code&gt;. &lt;strong&gt;Но не всегда&lt;/strong&gt;: изнутри &lt;code&gt;async&lt;/code&gt;-функции &lt;code&gt;nextTick&lt;/code&gt; теряет приоритет перед промисами — мы это замерили.&lt;/li&gt;&#xA;&lt;li&gt;Объект &lt;code&gt;process&lt;/code&gt; тоже глобальный, но он большой — ему посвящена &lt;a href=&#34;https://hackerx.ru/node-js-process/&#34;&gt;отдельная статья&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;В Node нет &lt;code&gt;window&lt;/code&gt;, но есть свой набор объектов, доступных в любом файле без единого импорта. За последние годы этот набор сильно вырос: половина того, ради чего раньше ставили пакеты, теперь встроена в платформу.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Машинное обучение: что это и зачем разработчику в 2026</title>
      <link>https://hackerx.ru/machine-learning-python/</link>
      <pubDate>Thu, 07 Dec 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/machine-learning-python/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Машинное обучение переворачивает обычное программирование:&lt;/strong&gt; вместо правил вы даёте примеры, а алгоритм выводит правила сам.&lt;/li&gt;&#xA;&lt;li&gt;Три вида: &lt;strong&gt;с учителем&lt;/strong&gt; (данные + ответы), &lt;strong&gt;без учителя&lt;/strong&gt; (только данные, ищем структуру), &lt;strong&gt;с подкреплением&lt;/strong&gt; (обучение методом проб).&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Python выбирают не за скорость, а за экосистему:&lt;/strong&gt; тяжёлые вычисления идут в C-библиотеках и на видеокарте, Python — удобный интерфейс.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Большие языковые модели не отменили классический ML&lt;/strong&gt; — они закрыли текст и генерацию, но прогнозы и аналитику по-прежнему делают классические модели.&lt;/li&gt;&#xA;&lt;li&gt;Главный навык — &lt;strong&gt;распознать, где ML нужен, а где задача решается обычным кодом или готовым API&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Код в статье концептуальный и не запускался — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Свой модуль в Node.js и публикация в NPM</title>
      <link>https://hackerx.ru/node-js-npm-module/</link>
      <pubDate>Fri, 24 Nov 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-npm-module/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Модуль в Node — это каталог с &lt;code&gt;package.json&lt;/code&gt;. Ничего больше не требуется.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Точка входа задаётся полем &lt;code&gt;exports&lt;/code&gt;, а не &lt;code&gt;main&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;main&lt;/code&gt; — легаси; &lt;code&gt;exports&lt;/code&gt; умеет подпути и, главное, &lt;strong&gt;закрывает внутренности пакета&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Проверено: попытка импортировать внутренний файл в обход &lt;code&gt;exports&lt;/code&gt; падает с &lt;code&gt;ERR_PACKAGE_PATH_NOT_EXPORTED&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;&amp;quot;type&amp;quot;: &amp;quot;module&amp;quot;&lt;/code&gt; включает ESM. Без него Node будет считать &lt;code&gt;.js&lt;/code&gt; файлы CommonJS.&lt;/li&gt;&#xA;&lt;li&gt;Перед публикацией — &lt;code&gt;npm publish --dry-run&lt;/code&gt; и &lt;code&gt;npm pack&lt;/code&gt;: они показывают, что реально уедет в реестр.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Модуль в Node устроен предельно просто: каталог, в нём &lt;code&gt;package.json&lt;/code&gt;, в нём поле с точкой входа. Всё остальное — детали, но именно в них за последние годы всё и поменялось.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Node.js Promise: промисы и async/await на практике</title>
      <link>https://hackerx.ru/node-js-promise/</link>
      <pubDate>Sat, 19 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-promise/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Promise&lt;/strong&gt; — объект, представляющий результат операции, который ещё не готов. Три состояния: &lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;fulfilled&lt;/code&gt;, &lt;code&gt;rejected&lt;/code&gt;. Состояние меняется только из &lt;code&gt;pending&lt;/code&gt; и только один раз.&lt;/li&gt;&#xA;&lt;li&gt;В 2026 промисы почти не создают руками. У Node есть промис-версии встроенных модулей (&lt;code&gt;node:fs/promises&lt;/code&gt;, &lt;code&gt;node:timers/promises&lt;/code&gt;), а старые колбэк-функции оборачивает &lt;code&gt;util.promisify&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Рабочий синтаксис — &lt;code&gt;async/await&lt;/code&gt;. &lt;code&gt;Promise.all&lt;/code&gt; — для независимых задач, &lt;code&gt;Promise.allSettled&lt;/code&gt; — когда нужны все результаты, включая упавшие.&lt;/li&gt;&#xA;&lt;li&gt;Самая дорогая ошибка — &lt;code&gt;await&lt;/code&gt; внутри цикла. В нашем замере пять задач по 200 мс заняли &lt;strong&gt;1021 мс&lt;/strong&gt; в цикле против &lt;strong&gt;204 мс&lt;/strong&gt; через &lt;code&gt;Promise.all&lt;/code&gt; — разница в 5 раз.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;figure class=&#34;illus&#34; role=&#34;img&#34; aria-label=&#34;Из состояния pending промис переходит либо в fulfilled с обработкой через then, либо в rejected с обработкой через catch&#34;&gt;&lt;svg viewBox=&#34;0 0 1200 430&#34; preserveAspectRatio=&#34;xMidYMid meet&#34; role=&#34;presentation&#34; focusable=&#34;false&#34;&gt;&#xA;  &lt;text x=&#34;40&#34; y=&#34;46&#34; class=&#34;il-tag&#34;&gt;NODE.JS · ПРОМИСЫ И ASYNC/AWAIT&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;90&#34; y=&#34;176&#34; width=&#34;260&#34; height=&#34;110&#34; rx=&#34;14&#34; class=&#34;il-panel&#34;/&gt;&#xA;  &lt;rect x=&#34;90&#34; y=&#34;176&#34; width=&#34;260&#34; height=&#34;110&#34; rx=&#34;14&#34; class=&#34;il-stroke&#34;/&gt;&#xA;  &lt;text x=&#34;220&#34; y=&#34;222&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;pending&lt;/text&gt;&#xA;  &lt;text x=&#34;220&#34; y=&#34;252&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;ожидание · результата ещё нет&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;620&#34; y=&#34;86&#34; width=&#34;300&#34; height=&#34;120&#34; rx=&#34;14&#34; class=&#34;il-ok-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;620&#34; y=&#34;86&#34; width=&#34;300&#34; height=&#34;120&#34; rx=&#34;14&#34; class=&#34;il-ok-line&#34;/&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;128&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;fulfilled&lt;/text&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;158&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34; style=&#34;fill:#1baf7a&#34;&gt;.then(value)&lt;/text&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;188&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;успех → значение&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;rect x=&#34;620&#34; y=&#34;256&#34; width=&#34;300&#34; height=&#34;120&#34; rx=&#34;14&#34; class=&#34;il-bad-soft&#34;/&gt;&#xA;  &lt;rect x=&#34;620&#34; y=&#34;256&#34; width=&#34;300&#34; height=&#34;120&#34; rx=&#34;14&#34; class=&#34;il-bad-line&#34;/&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;298&#34; text-anchor=&#34;middle&#34; class=&#34;il-lbl&#34;&gt;rejected&lt;/text&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;328&#34; text-anchor=&#34;middle&#34; class=&#34;il-mono&#34; style=&#34;fill:#e34948&#34;&gt;.catch(error)&lt;/text&gt;&#xA;  &lt;text x=&#34;770&#34; y=&#34;358&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;ошибка → причина&lt;/text&gt;&#xA;&#xA;  &#xA;  &lt;path d=&#34;M 352 216 L 500 216 L 500 146 L 614 146&#34; class=&#34;il-ok-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M614,146 l-13,-6 l0,12 z&#34; style=&#34;fill:#1baf7a&#34;/&gt;&#xA;  &lt;path d=&#34;M 352 246 L 500 246 L 500 316 L 614 316&#34; class=&#34;il-bad-line&#34; fill=&#34;none&#34;/&gt;&lt;path class=&#34;il-ah&#34; d=&#34;M614,316 l-13,-6 l0,12 z&#34; style=&#34;fill:#e34948&#34;/&gt;&#xA;&#xA;  &#xA;  &lt;text x=&#34;960&#34; y=&#34;150&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;await превращает&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;174&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;результат в значение,&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;304&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;а отклонение —&lt;/text&gt;&#xA;  &lt;text x=&#34;960&#34; y=&#34;328&#34; text-anchor=&#34;middle&#34; class=&#34;il-sm&#34;&gt;в исключение для try/catch&lt;/text&gt;&#xA;&#xA;  &lt;text x=&#34;600&#34; y=&#34;410&#34; text-anchor=&#34;middle&#34; class=&#34;il-tag&#34;&gt;СОСТОЯНИЕ МЕНЯЕТСЯ ОДИН РАЗ И НАВСЕГДА&lt;/text&gt;&#xA;&lt;/svg&gt;&#xA;&lt;figcaption class=&#34;illus-cap&#34;&gt;Состояния промиса: pending → fulfilled или rejected&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&lt;p&gt;Асинхронность — причина, по которой Node.js вообще существует: пока один запрос ждёт ответа от базы, процесс обслуживает другие. Вопрос лишь в том, как этим ожиданием управлять из кода. За десять лет ответ менялся дважды: сначала колбэки, потом промисы, теперь &lt;code&gt;async/await&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>child_process в Node.js: exec, execFile, spawn и fork</title>
      <link>https://hackerx.ru/node-js-child-process/</link>
      <pubDate>Fri, 18 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-child-process/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Четыре способа запустить внешнюю программу: &lt;code&gt;exec&lt;/code&gt;, &lt;code&gt;execFile&lt;/code&gt;, &lt;code&gt;spawn&lt;/code&gt;, &lt;code&gt;fork&lt;/code&gt;. Различаются двумя вещами — поднимают ли оболочку и буферизуют ли вывод.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;exec&lt;/code&gt; запускает оболочку и разбирает вашу строку как команду.&lt;/strong&gt; Отсюда обе его беды: ломается на путях с пробелами и выполняет то, что пришло от пользователя.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;По умолчанию берите &lt;code&gt;execFile&lt;/code&gt; или &lt;code&gt;spawn&lt;/code&gt;&lt;/strong&gt; — они передают аргументы массивом, и интерпретировать их некому.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;exec&lt;/code&gt;/&lt;code&gt;execFile&lt;/code&gt; копят весь вывод в память: &lt;code&gt;maxBuffer&lt;/code&gt; по умолчанию 1 МБ, при превышении — &lt;code&gt;ERR_CHILD_PROCESS_STDIO_MAXBUFFER&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;spawn&lt;/code&gt; отдаёт вывод потоком — для долгих задач и больших объёмов нужен именно он.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Node однопоточен для вашего JavaScript, но никто не мешает запустить рядом другой процесс: конвертер видео, &lt;code&gt;git&lt;/code&gt;, скрипт на Python. За это отвечает встроенный модуль &lt;code&gt;node:child_process&lt;/code&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Изменение стилей и классов: jQuery .css() и нативный JS</title>
      <link>https://hackerx.ru/jquery-izmenenie-stilei/</link>
      <pubDate>Fri, 18 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/jquery-izmenenie-stilei/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;jQuery: &lt;code&gt;$el.css(&#39;color&#39;, &#39;red&#39;)&lt;/code&gt;. Нативно: &lt;code&gt;el.style.color = &#39;red&#39;&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Чтение стиля почти всегда возвращает не то, что вы записали:&lt;/strong&gt; браузер отдаёт вычисленное значение — &lt;code&gt;rgb(255, 0, 0)&lt;/code&gt; вместо &lt;code&gt;red&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;el.style&lt;/code&gt; видит &lt;strong&gt;только инлайновые&lt;/strong&gt; стили. Правило из CSS-файла там пустое — нужен &lt;code&gt;getComputedStyle&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Главный совет: не меняйте стили из JavaScript.&lt;/strong&gt; Переключайте классы, а оформление держите в CSS.&lt;/li&gt;&#xA;&lt;li&gt;Когда значение всё-таки динамическое (прогресс, координаты) — отдавайте его &lt;strong&gt;CSS-переменной&lt;/strong&gt;, а не свойством.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Паттерны проектирования в Node.js: какие реально нужны</title>
      <link>https://hackerx.ru/node-js-shabloni-proektirovanie/</link>
      <pubDate>Fri, 18 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-shabloni-proektirovanie/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Половина классических паттернов в JavaScript встроена в язык&lt;/strong&gt; и не нужна как отдельная конструкция.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Синглтон в Node — это модуль:&lt;/strong&gt; он кэшируется, первый импорт выполняет код, остальные получают тот же объект.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Наблюдатель — это &lt;a href=&#34;https://hackerx.ru/nodejs-events-object-eventemitter/&#34;&gt;EventEmitter&lt;/a&gt;&lt;/strong&gt;, итератор — протокол &lt;code&gt;for..of&lt;/code&gt;, стратегия — просто функция как аргумент.&lt;/li&gt;&#xA;&lt;li&gt;Реально полезны в Node: &lt;strong&gt;фабрика&lt;/strong&gt;, &lt;strong&gt;фасад&lt;/strong&gt; (обёртка над сложным API), &lt;strong&gt;middleware&lt;/strong&gt; (цепочка обработчиков).&lt;/li&gt;&#xA;&lt;li&gt;Главное правило: &lt;strong&gt;паттерн — ответ на проблему, а не украшение.&lt;/strong&gt; Сначала проблема, потом паттерн.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Изменить содержимое элемента: html(), text() и XSS</title>
      <link>https://hackerx.ru/zamena-soderjimogo-jquery/</link>
      <pubDate>Tue, 15 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/zamena-soderjimogo-jquery/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;jQuery: &lt;code&gt;.html()&lt;/code&gt; — разметка, &lt;code&gt;.text()&lt;/code&gt; — текст. Нативно: &lt;code&gt;innerHTML&lt;/code&gt; и &lt;code&gt;textContent&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Выбор между ними — вопрос безопасности, а не стиля.&lt;/strong&gt; &lt;code&gt;innerHTML&lt;/code&gt; с данными пользователя — это XSS.&lt;/li&gt;&#xA;&lt;li&gt;Миф: «&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; через &lt;code&gt;innerHTML&lt;/code&gt; не выполняется, значит безопасно». &lt;strong&gt;Не значит:&lt;/strong&gt; &lt;code&gt;&amp;lt;img src=x onerror=alert(1)&amp;gt;&lt;/code&gt; выполнится прекрасно.&lt;/li&gt;&#xA;&lt;li&gt;Правило: &lt;strong&gt;данные от пользователя — только &lt;code&gt;textContent&lt;/code&gt;.&lt;/strong&gt; Нужна разметка — санитизируйте DOMPurify, а не самописным фильтром.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;textContent&lt;/code&gt; ещё и быстрее &lt;code&gt;innerText&lt;/code&gt;: последний учитывает отображение и вызывает пересчёт стилей.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Объект process в Node.js: argv, env, память и выход</title>
      <link>https://hackerx.ru/node-js-process/</link>
      <pubDate>Mon, 14 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-process/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;process&lt;/code&gt; — глобальный объект, представляющий текущий процесс: аргументы, окружение, память, ввод-вывод, завершение.&lt;/li&gt;&#xA;&lt;li&gt;Аргументы разбирайте встроенным &lt;code&gt;util.parseArgs&lt;/code&gt;, а не вручную по &lt;code&gt;process.argv&lt;/code&gt;: он сам поймёт &lt;code&gt;--port 8080&lt;/code&gt; и флаги.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Любое значение в &lt;code&gt;process.env&lt;/code&gt; — строка.&lt;/strong&gt; Записали число 8080 — прочитаете &lt;code&gt;&amp;quot;8080&amp;quot;&lt;/code&gt;. Строка &lt;code&gt;&amp;quot;false&amp;quot;&lt;/code&gt; при этом истинна.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;process.exit()&lt;/code&gt; обрывает процесс немедленно: незавершённые записи и ответы клиентам теряются. Правильно — &lt;code&gt;process.exitCode = 1&lt;/code&gt; и дать процессу закончить самому.&lt;/li&gt;&#xA;&lt;li&gt;Относительные пути считаются от &lt;code&gt;process.cwd()&lt;/code&gt; — каталога запуска, а не от файла модуля.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;&lt;code&gt;process&lt;/code&gt; доступен в любом файле без импорта — он один из &lt;a href=&#34;https://hackerx.ru/node-global-objects/&#34;&gt;глобальных объектов Node&lt;/a&gt; — и знает о процессе всё: с какими аргументами его запустили, какие переменные окружения видны, сколько памяти занято и как корректно завершиться. Разберём то, что нужно на практике.&lt;/p&gt;</description>
    </item>
    <item>
      <title>fs.appendFile(): как дописать текст в конец файла</title>
      <link>https://hackerx.ru/node-fs-appendfile/</link>
      <pubDate>Sun, 13 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-fs-appendfile/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;appendFile&lt;/code&gt; дописывает данные в конец файла, а &lt;code&gt;writeFile&lt;/code&gt; — затирает содержимое целиком. Это единственное различие между ними.&lt;/li&gt;&#xA;&lt;li&gt;Если файла нет, &lt;code&gt;appendFile&lt;/code&gt; &lt;strong&gt;создаст его сам&lt;/strong&gt; — предварительная проверка не нужна.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;writeFile(path, data, { flag: &#39;a&#39; })&lt;/code&gt; делает ровно то же самое: &lt;code&gt;appendFile&lt;/code&gt; — просто удобное сокращение.&lt;/li&gt;&#xA;&lt;li&gt;В цикле &lt;code&gt;appendFile&lt;/code&gt; дорог: он открывает и закрывает файл на каждый вызов. В нашем замере 2000 записей заняли &lt;strong&gt;433 мс&lt;/strong&gt; против &lt;strong&gt;64 мс&lt;/strong&gt; через один дескриптор — разница в 6.8 раза.&lt;/li&gt;&#xA;&lt;li&gt;Для журналов и больших объёмов берите открытый дескриптор или поток, а не &lt;code&gt;appendFile&lt;/code&gt; в цикле.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Дописать строку в конец файла — задача на одну строку кода, и &lt;code&gt;fs.appendFile&lt;/code&gt; из &lt;a href=&#34;https://hackerx.ru/modul-fs-rabota-s-faylami-v-node-js/&#34;&gt;модуля &lt;code&gt;fs&lt;/code&gt;&lt;/a&gt; её решает. Проблемы начинаются, когда этой одной строкой пишут журнал в цикле.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MongoDB CRUD: вставка, выборка, обновление и удаление</title>
      <link>https://hackerx.ru/mongodb-crud/</link>
      <pubDate>Sun, 13 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/mongodb-crud/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Четыре операции покрывают почти всё: &lt;code&gt;insertOne&lt;/code&gt;/&lt;code&gt;insertMany&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;/&lt;code&gt;findOne&lt;/code&gt;, &lt;code&gt;updateOne&lt;/code&gt;/&lt;code&gt;updateMany&lt;/code&gt;, &lt;code&gt;deleteOne&lt;/code&gt;/&lt;code&gt;deleteMany&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;matchedCount&lt;/code&gt; и &lt;code&gt;modifiedCount&lt;/code&gt; — разные вещи.&lt;/strong&gt; На повторном обновлении теми же данными мы получили &lt;code&gt;matched: 2, modified: 0&lt;/code&gt;: документы нашлись, но записи не было.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;_id&lt;/code&gt; — это &lt;code&gt;ObjectId&lt;/code&gt;, а не строка.&lt;/strong&gt; Поиск по строке вернул &lt;code&gt;null&lt;/code&gt;, по &lt;code&gt;ObjectId&lt;/code&gt; — документ. Самая частая ошибка при передаче id из HTTP.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Без индекса — полный перебор.&lt;/strong&gt; Замер: &lt;code&gt;COLLSCAN&lt;/code&gt;, просмотрено 20 000 документов. С индексом — &lt;code&gt;FETCH&lt;/code&gt; и &lt;strong&gt;1 документ&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Удаление несуществующего документа не ошибка: &lt;code&gt;deletedCount: 0&lt;/code&gt;, исключения нет.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;CRUD в MongoDB — это четыре группы методов коллекции. Синтаксис простой, и именно поэтому большинство проблем возникает не в нём, а в деталях: что вернула операция, какого типа &lt;code&gt;_id&lt;/code&gt; и почему запрос перебирает всю коллекцию.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MongoDB: что это, зачем нужна и когда не нужна</title>
      <link>https://hackerx.ru/chto-takoe-mongodb/</link>
      <pubDate>Sun, 13 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/chto-takoe-mongodb/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;MongoDB хранит &lt;strong&gt;документы&lt;/strong&gt; — по сути объекты JSON — вместо строк в таблицах. Связанные данные лежат вместе, а не собираются JOIN-ами.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Схемы нет.&lt;/strong&gt; Мы проверили: в одну коллекцию спокойно легли документы с разными наборами полей, никто не возразил. Это и главное удобство, и главный риск — опечатка в имени поля не ошибка, а новое поле.&lt;/li&gt;&#xA;&lt;li&gt;Выигрывает там, где форма данных разнородна или меняется; &lt;strong&gt;проигрывает там, где нужны связи, жёсткая схема и транзакции&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Индексы обязательны так же, как в SQL: без них база перебирает коллекцию целиком.&lt;/li&gt;&#xA;&lt;li&gt;«MongoDB теряет данные» — про версии десятилетней давности. Сегодня запись подтверждается по умолчанию.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;MongoDB — самая популярная документоориентированная база данных, и почти вся путаница вокруг неё возникает из-за одного вопроса: чем документ отличается от строки таблицы и что это меняет на практике.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Получить значение атрибута: jQuery .attr() и нативный JS</title>
      <link>https://hackerx.ru/get-attribute-value/</link>
      <pubDate>Thu, 10 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/get-attribute-value/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;jQuery: &lt;code&gt;$el.attr(&#39;href&#39;)&lt;/code&gt;. Нативно: &lt;code&gt;el.getAttribute(&#39;href&#39;)&lt;/code&gt; — разница почти только в длине записи.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Главная ловушка не в синтаксисе, а в различии атрибута и свойства.&lt;/strong&gt; Атрибут — то, что написано в HTML. Свойство — текущее состояние DOM. Они расходятся.&lt;/li&gt;&#xA;&lt;li&gt;Для &lt;code&gt;checked&lt;/code&gt;, &lt;code&gt;selected&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt; читайте &lt;strong&gt;свойство&lt;/strong&gt; (&lt;code&gt;.prop()&lt;/code&gt; или &lt;code&gt;el.checked&lt;/code&gt;), иначе получите исходное значение вместо актуального.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;data-*&lt;/code&gt; удобнее читать через &lt;code&gt;el.dataset&lt;/code&gt;: &lt;code&gt;data-user-id&lt;/code&gt; → &lt;code&gt;dataset.userId&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;getAttribute&lt;/code&gt; вернёт &lt;code&gt;null&lt;/code&gt;, если атрибута нет, и пустую строку, если он есть, но пустой, — это разные случаи.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Удалить атрибут: jQuery .removeAttr() и нативный JS</title>
      <link>https://hackerx.ru/delete-attribute-jquery/</link>
      <pubDate>Thu, 10 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/delete-attribute-jquery/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;jQuery: &lt;code&gt;$el.removeAttr(&#39;title&#39;)&lt;/code&gt;. Нативно: &lt;code&gt;el.removeAttribute(&#39;title&#39;)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Удаление атрибута и установка пустого значения — разные вещи.&lt;/strong&gt; &lt;code&gt;alt=&amp;quot;&amp;quot;&lt;/code&gt; означает «картинка декоративная», отсутствие &lt;code&gt;alt&lt;/code&gt; — «подпись забыли».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для &lt;code&gt;disabled&lt;/code&gt;, &lt;code&gt;checked&lt;/code&gt;, &lt;code&gt;readonly&lt;/code&gt; удаление атрибута может не сработать&lt;/strong&gt;: если состояние меняли из кода, живёт свойство. Нужен &lt;code&gt;.prop(&#39;disabled&#39;, false)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;jQuery умеет удалять несколько атрибутов через пробел; нативно нужен цикл.&lt;/li&gt;&#xA;&lt;li&gt;Удаление &lt;code&gt;data-*&lt;/code&gt; через &lt;code&gt;delete el.dataset.key&lt;/code&gt; — рабочий способ, но jQuery-кэш &lt;code&gt;.data()&lt;/code&gt; при этом не обновится.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Установить или изменить атрибут: jQuery и нативный JS</title>
      <link>https://hackerx.ru/set-and-edit-attribut-value/</link>
      <pubDate>Thu, 10 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/set-and-edit-attribut-value/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;jQuery: &lt;code&gt;$el.attr(&#39;src&#39;, &#39;/a.jpg&#39;)&lt;/code&gt;. Нативно: &lt;code&gt;el.setAttribute(&#39;src&#39;, &#39;/a.jpg&#39;)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Несколько атрибутов разом&lt;/strong&gt; jQuery принимает объектом — это его единственное реальное преимущество здесь.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для полей формы &lt;code&gt;.attr()&lt;/code&gt; не работает так, как ждут.&lt;/strong&gt; &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;checked&lt;/code&gt;, &lt;code&gt;disabled&lt;/code&gt; меняются через свойство: &lt;code&gt;.prop()&lt;/code&gt; или &lt;code&gt;el.value&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Установка атрибута &lt;strong&gt;не удаляет&lt;/strong&gt; остальные: &lt;code&gt;setAttribute(&#39;class&#39;, &#39;a&#39;)&lt;/code&gt; затрёт все классы, а &lt;code&gt;classList.add(&#39;a&#39;)&lt;/code&gt; — нет.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Подстановка данных пользователя в &lt;code&gt;href&lt;/code&gt; или &lt;code&gt;src&lt;/code&gt; — дыра.&lt;/strong&gt; Значение &lt;code&gt;javascript:...&lt;/code&gt; выполнит код; проверяйте протокол по белому списку.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Автозаполнение поля: jQuery UI Autocomplete и datalist</title>
      <link>https://hackerx.ru/jquery-ui-autocomplete/</link>
      <pubDate>Wed, 02 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/jquery-ui-autocomplete/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;jQuery UI в режиме поддержки:&lt;/strong&gt; критические правки выходят, новых возможностей нет. Для нового кода его не берут.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Нативный &lt;code&gt;datalist&lt;/code&gt; решает простой случай без единой строки JavaScript&lt;/strong&gt; — но почти не стилизуется и ведёт себя по-разному в браузерах.&lt;/li&gt;&#xA;&lt;li&gt;Свой компонент нужен, когда важны внешний вид и логика фильтрации. Это не сложно, но требует двух вещей, о которых забывают.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;debounce&lt;/code&gt; обязателен&lt;/strong&gt;, иначе каждый символ уходит запросом на сервер.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;AbortController&lt;/code&gt; обязателен&lt;/strong&gt;, иначе ответ на старый запрос перезапишет актуальный — классическая гонка.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации jQuery UI и MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Как узнать класс элемента: jQuery и нативный JavaScript</title>
      <link>https://hackerx.ru/jquery-get-html-class/</link>
      <pubDate>Tue, 01 Aug 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/jquery-get-html-class/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;В jQuery класс читают через &lt;code&gt;$el.attr(&#39;class&#39;)&lt;/code&gt;, проверяют — &lt;code&gt;$el.hasClass(&#39;active&#39;)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Нативный аналог удобнее:&lt;/strong&gt; &lt;code&gt;el.className&lt;/code&gt; даёт строку, а &lt;code&gt;el.classList&lt;/code&gt; — коллекцию с &lt;code&gt;contains&lt;/code&gt;, &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;remove&lt;/code&gt;, &lt;code&gt;toggle&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;classList.contains(&#39;active&#39;)&lt;/code&gt; полностью заменяет &lt;code&gt;hasClass&lt;/code&gt; и работает во всех живых браузерах.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ради классов jQuery не нужен.&lt;/strong&gt; Если он уже в проекте — пользуйтесь; тянуть его ради этой задачи незачем.&lt;/li&gt;&#xA;&lt;li&gt;Частая путаница: класс есть в разметке, а стиль не применился — это вопрос специфичности CSS, а не JavaScript.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры в этой статье не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где мы приводим фактический вывод консоли. Код приведён по документации jQuery и MDN. Говорим об этом прямо, а не ставим бейдж «проверено» там, где проверки не было.&lt;/p&gt;</description>
    </item>
    <item>
      <title>CSS-препроцессоры в 2026: нужны ли Sass и Less сегодня</title>
      <link>https://hackerx.ru/css-%D0%BF%D1%80%D0%B5%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D1%8B/</link>
      <pubDate>Mon, 31 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/css-%D0%BF%D1%80%D0%B5%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D1%8B/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Препроцессоры (Sass, Less, Stylus) добавляли в CSS то, чего в нём не было: переменные, вложенность, миксины, математику.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Половину этого CSS получил сам:&lt;/strong&gt; нативные переменные, вложенность (nesting), функции &lt;code&gt;min/max/clamp&lt;/code&gt;, &lt;code&gt;calc()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;CSS-переменная ≠ Sass-переменная.&lt;/strong&gt; Sass подставляется при сборке, нативная живёт в браузере и меняется из JS и по теме.&lt;/li&gt;&#xA;&lt;li&gt;Из препроцессоров победил &lt;strong&gt;Sass (SCSS)&lt;/strong&gt;; Less — в старых проектах, Stylus почти заброшен.&lt;/li&gt;&#xA;&lt;li&gt;Для многих проектов &lt;strong&gt;чистого CSS уже достаточно&lt;/strong&gt; — на одну зависимость в сборке меньше.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не собирались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Код дан по документации Sass и MDN. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Geolocation API: как определить местоположение в браузере</title>
      <link>https://hackerx.ru/html5-geolocation-api/</link>
      <pubDate>Mon, 31 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/html5-geolocation-api/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Geolocation API определяет местоположение через &lt;code&gt;navigator.geolocation&lt;/code&gt; — встроен в браузер, библиотек не нужно.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Работает только по HTTPS.&lt;/strong&gt; На HTTP браузер молча не отдаст координаты — самая частая причина «не работает».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Пользователь всегда спрашивается&lt;/strong&gt;, и отказ нужно обрабатывать. Без разрешения координат не будет.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;getCurrentPosition&lt;/code&gt; — один раз, &lt;code&gt;watchPosition&lt;/code&gt; — следит за перемещением (и его надо снимать через &lt;code&gt;clearWatch&lt;/code&gt;).&lt;/li&gt;&#xA;&lt;li&gt;Точность разная: GPS — метры, IP — километры. Поле &lt;code&gt;accuracy&lt;/code&gt; даёт радиус погрешности; проверяйте его.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались в браузере — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Код дан по документации MDN. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Memcached в 2026: жив ли и чем заменить</title>
      <link>https://hackerx.ru/memcached-nosql/</link>
      <pubDate>Mon, 31 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/memcached-nosql/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Memcached — хранилище «ключ-значение» в оперативной памяти. Умеет ровно одно: положить строку по ключу и взять её обратно.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Он не умер, но для нового проекта его почти не выбирают.&lt;/strong&gt; Redis делает всё то же самое плюс структуры данных, TTL, персистентность и pub/sub.&lt;/li&gt;&#xA;&lt;li&gt;Аргумент «Memcached быстрее» сегодня не работает: на простом кэше разница в пределах погрешности, оба в памяти.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Где он реально выигрывает — многопоточность.&lt;/strong&gt; Memcached использует несколько ядер, Redis выполняет команды в одном потоке.&lt;/li&gt;&#xA;&lt;li&gt;Практическое правило 2026: &lt;strong&gt;новый проект — Redis&lt;/strong&gt;; Memcached — если он у вас уже есть и всё устраивает.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Memcached — один из самых заслуженных инструментов в вебе: он появился в 2003 году и годами держал кэш всего крупного, что вы знаете. Вопрос сегодня не в том, что это такое, а в том, стоит ли брать его в новый проект.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Показать местоположение на карте: Google и Яндекс.Карты</title>
      <link>https://hackerx.ru/html5-geolocation-api-using-google-and-yandex-api-maps/</link>
      <pubDate>Mon, 31 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/html5-geolocation-api-using-google-and-yandex-api-maps/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Схема всегда одна: &lt;a href=&#34;https://hackerx.ru/html5-geolocation-api/&#34;&gt;Geolocation API&lt;/a&gt; даёт координаты, карта их &lt;strong&gt;показывает&lt;/strong&gt;. Это два независимых шага.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Карты Google и Яндекс стали платными.&lt;/strong&gt; Оба требуют ключ API и берут деньги за запросы сверх лимита.&lt;/li&gt;&#xA;&lt;li&gt;Если местоположение нужно только &lt;strong&gt;получить&lt;/strong&gt; — карта не нужна вовсе. Часто хватает статической картинки вместо тяжёлого виджета.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Библиотеки карт тяжёлые&lt;/strong&gt; (сотни КБ JS) — грузите их лениво, не блокируя отрисовку страницы.&lt;/li&gt;&#xA;&lt;li&gt;Бесплатная альтернатива — &lt;strong&gt;OpenStreetMap + Leaflet&lt;/strong&gt;: без ключа и без оплаты для базового использования.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались, API-ключи не подключались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Код дан по документации Google Maps, Яндекс.Карт и MDN. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Socket.io: чат на Node.js и что он добавляет к WebSocket</title>
      <link>https://hackerx.ru/node-js-socket-io/</link>
      <pubDate>Sun, 30 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-socket-io/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Socket.io — &lt;strong&gt;не WebSocket, а библиотека поверх него&lt;/strong&gt; со своим протоколом. Клиент Socket.io и чистый WebSocket-сервер друг с другом не соединятся.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;io.emit&lt;/code&gt; шлёт всем &lt;strong&gt;включая отправителя&lt;/strong&gt;, &lt;code&gt;socket.broadcast.emit&lt;/code&gt; — &lt;strong&gt;всем кроме него&lt;/strong&gt;. Проверено обоими клиентами.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Комнаты изолируют&lt;/strong&gt;: сообщение в комнату получил только тот, кто в неё вошёл.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;socket.id&lt;/code&gt; меняется при переподключении.&lt;/strong&gt; Замерили: после обрыва клиент вернулся с новым id. Привязывать к нему состояние нельзя.&lt;/li&gt;&#xA;&lt;li&gt;Из коробки: автопереподключение, подтверждения (&lt;code&gt;emitWithAck&lt;/code&gt;), откат на polling. Ради этого его и берут.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Socket.io — самый частый ответ на «сделать чат на Node». Разберём, что он даёт поверх &lt;a href=&#34;https://hackerx.ru/what-are-websocket/&#34;&gt;чистого WebSocket&lt;/a&gt; и где расставлены грабли.&lt;/p&gt;</description>
    </item>
    <item>
      <title>WebSocket: как устроен и когда он не нужен</title>
      <link>https://hackerx.ru/what-are-websocket/</link>
      <pubDate>Sun, 30 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/what-are-websocket/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;WebSocket начинается как обычный HTTP-запрос.&lt;/strong&gt; Это &lt;code&gt;GET&lt;/code&gt; с заголовком &lt;code&gt;Upgrade: websocket&lt;/code&gt;; сервер отвечает &lt;code&gt;101 Switching Protocols&lt;/code&gt;, и тот же TCP-сокет меняет протокол.&lt;/li&gt;&#xA;&lt;li&gt;Ключ рукопожатия считается детерминированно: &lt;code&gt;Sec-WebSocket-Accept = base64(sha1(ключ_клиента + GUID из RFC 6455))&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;После рукопожатия сервер пишет сам, без запроса&lt;/strong&gt; — в нашем демо клиент получил два сообщения, не отправив ни одного.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Клиент обязан маскировать&lt;/strong&gt; каждый фрейм, сервер — нет. Это требование стандарта, а не оптимизация.&lt;/li&gt;&#xA;&lt;li&gt;Сокет нужен не всегда: если данные идут только от сервера к клиенту — &lt;strong&gt;SSE проще&lt;/strong&gt; и работает поверх обычного HTTP.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Про WebSocket обычно рассказывают на уровне «постоянное соединение, сервер может слать сам». Это правда, но за ней прячется главное непонимание: &lt;strong&gt;откуда это соединение берётся&lt;/strong&gt;. Разберём на живом сервере, поднятом на голом &lt;code&gt;node:http&lt;/code&gt; — без единого пакета.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Вставка документов в MongoDB: insertOne и insertMany</title>
      <link>https://hackerx.ru/insert-documents-mongodb-crud/</link>
      <pubDate>Sun, 30 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/insert-documents-mongodb-crud/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;insertOne&lt;/code&gt; вставляет один документ, &lt;code&gt;insertMany&lt;/code&gt; — массив. База и коллекция создаются сами при первой записи.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;_id&lt;/code&gt; генерирует драйвер на клиенте&lt;/strong&gt;, а не сервер: &lt;code&gt;insertedId&lt;/code&gt; известен сразу после вызова.&lt;/li&gt;&#xA;&lt;li&gt;Дубликат &lt;code&gt;_id&lt;/code&gt; даёт &lt;code&gt;MongoServerError&lt;/code&gt; с &lt;strong&gt;кодом 11000&lt;/strong&gt;. Ловить нужно по &lt;code&gt;err.code&lt;/code&gt;, а не по тексту.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;insertMany&lt;/code&gt; — это одна отправка на сервер вместо N: цикл из &lt;code&gt;insertOne&lt;/code&gt; платит сетевым раундтрипом за каждый документ.&lt;/li&gt;&#xA;&lt;li&gt;Схемы нет: соседние документы могут иметь разные поля, и база не возразит.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Вставка — первая операция, с которой начинают работу с MongoDB, и самая простая из всех. Разберём её целиком, включая то, о чём обычно узнают уже в продакшене.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Сложность алгоритмов: время, память и сложность методов JS</title>
      <link>https://hackerx.ru/complexity-theory-algorithms/</link>
      <pubDate>Sun, 30 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/complexity-theory-algorithms/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Сложность бывает &lt;strong&gt;двух видов: временна́я&lt;/strong&gt; (как растёт время) и &lt;strong&gt;пространственная&lt;/strong&gt; (как растёт память). Их часто путают, а они в противофазе.&lt;/li&gt;&#xA;&lt;li&gt;Ускорение почти всегда покупается памятью: кэш, хеш-таблица, предвычисление — всё это O(n) памяти ради O(1) времени.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;У встроенных методов JS тоже есть сложность.&lt;/strong&gt; &lt;code&gt;includes&lt;/code&gt;, &lt;code&gt;indexOf&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt; — это O(n). Частая проверка вхождения через массив = скрытый O(n²).&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;Set.has&lt;/code&gt; и &lt;code&gt;Map.get&lt;/code&gt; — O(1). Замена массива на &lt;code&gt;Set&lt;/code&gt; для проверок — самая недооценённая оптимизация.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;[...arr]&lt;/code&gt; и &lt;code&gt;Object.assign&lt;/code&gt; копируют за O(n): в цикле это незаметно превращается в O(n²).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Оценки сложности — математика, а не замер; конкретные времена не измерялись. Бейджа «проверено» поэтому нет — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом.&lt;/p&gt;</description>
    </item>
    <item>
      <title>ORM в Node.js: Sequelize, Prisma и когда ORM не нужен</title>
      <link>https://hackerx.ru/orm-sequelize-node-js/</link>
      <pubDate>Sat, 29 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/orm-sequelize-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;ORM превращает строки таблицы в объекты кода:&lt;/strong&gt; &lt;code&gt;user.save()&lt;/code&gt; вместо &lt;code&gt;INSERT&lt;/code&gt;. Удобно на простых запросах, дорого на сложных.&lt;/li&gt;&#xA;&lt;li&gt;В 2026 для нового проекта чаще берут &lt;strong&gt;Prisma или Drizzle&lt;/strong&gt;; Sequelize жив, но воспринимается как наследие.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Проблема N+1&lt;/strong&gt; — главная ловушка: ORM незаметно делает сто один запрос там, где нужен один с JOIN.&lt;/li&gt;&#xA;&lt;li&gt;ORM &lt;strong&gt;защищает от инъекций&lt;/strong&gt;, пока вы не вставляете сырой SQL со строковой подстановкой в обход него.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;На сложных запросах честнее писать SQL&lt;/strong&gt; — ORM там либо тормозит, либо не выражает их, и вы всё равно уходите в сырой запрос.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались на живой базе — в отличие от &lt;a href=&#34;https://hackerx.ru/mongodb-crud/&#34;&gt;MongoDB&lt;/a&gt; и &lt;a href=&#34;https://hackerx.ru/redis-%D0%B8-node-js/&#34;&gt;Redis&lt;/a&gt;, где был фактический вывод. Код дан по документации Sequelize и Prisma. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Ключевые слова JavaScript: полный список и ловушки</title>
      <link>https://hackerx.ru/js-keywords/</link>
      <pubDate>Thu, 20 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/js-keywords/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Ключевые слова заняты грамматикой языка: переменную с таким именем объявить нельзя — будет &lt;code&gt;SyntaxError&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;await&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;, &lt;code&gt;static&lt;/code&gt;, &lt;code&gt;yield&lt;/code&gt; — контекстные:&lt;/strong&gt; ключевые только в определённом окружении, а в остальных это обычные имена.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Свойством объекта ключевое слово быть может:&lt;/strong&gt; &lt;code&gt;obj.class&lt;/code&gt; и &lt;code&gt;{ new: 1 }&lt;/code&gt; легальны с ES5. Запрет остался только на имена переменных.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;enum&lt;/code&gt;, &lt;code&gt;implements&lt;/code&gt;, &lt;code&gt;package&lt;/code&gt; зарезервированы &lt;strong&gt;про запас&lt;/strong&gt; и в языке не используются до сих пор.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;undefined&lt;/code&gt; — не ключевое слово, а глобальное свойство. В старом коде его можно было переопределить; отсюда приём &lt;code&gt;void 0&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>React в 2026: как начать и почему не create-react-app</title>
      <link>https://hackerx.ru/install-react-js/</link>
      <pubDate>Sun, 16 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/install-react-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;create-react-app&lt;/code&gt; мёртв&lt;/strong&gt; — команда React больше его не рекомендует. Начинать проект с него в 2026 — ошибка.&lt;/li&gt;&#xA;&lt;li&gt;Что вместо: &lt;strong&gt;Vite&lt;/strong&gt; для клиентского приложения (SPA), &lt;strong&gt;Next.js&lt;/strong&gt; — когда нужны SSR, маршрутизация и SEO.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Классовые компоненты ушли.&lt;/strong&gt; Современный React — функции и хуки (&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;); классы только в старом коде.&lt;/li&gt;&#xA;&lt;li&gt;React — &lt;strong&gt;библиотека, а не фреймворк&lt;/strong&gt;: он про интерфейс, а сборку и маршрутизацию добавляют инструменты вокруг.&lt;/li&gt;&#xA;&lt;li&gt;Redux нужен реже: для локального состояния — &lt;code&gt;useState&lt;/code&gt;, для общего — Context или лёгкие библиотеки.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Проект не собирался, команды не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Код и команды даны по документации React, Vite и Next.js. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Массивы в JavaScript: методы, мутации и подводные камни</title>
      <link>https://hackerx.ru/javascript-array/</link>
      <pubDate>Sat, 15 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/javascript-array/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Главное деление методов — мутирующие и нет.&lt;/strong&gt; &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;splice&lt;/code&gt;, &lt;code&gt;reverse&lt;/code&gt; меняют исходный массив; &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;slice&lt;/code&gt; возвращают новый.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;sort()&lt;/code&gt; без компаратора сортирует как строки:&lt;/strong&gt; &lt;code&gt;[10, 9, 1]&lt;/code&gt; превратится в &lt;code&gt;[1, 10, 9]&lt;/code&gt;. Для чисел всегда &lt;code&gt;sort((a, b) =&amp;gt; a - b)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;slice&lt;/code&gt; и &lt;code&gt;splice&lt;/code&gt; — одна буква разницы и противоположное поведение. Классический источник багов.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;С ES2023 у мутирующих методов есть безмутационные пары:&lt;/strong&gt; &lt;code&gt;toSorted&lt;/code&gt;, &lt;code&gt;toReversed&lt;/code&gt;, &lt;code&gt;toSpliced&lt;/code&gt;, &lt;code&gt;with&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;arr.at(-1)&lt;/code&gt; — последний элемент без &lt;code&gt;arr[arr.length - 1]&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Что такое JavaScript и где он сегодня работает</title>
      <link>https://hackerx.ru/what-is-javascript/</link>
      <pubDate>Wed, 12 Jul 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/what-is-javascript/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;JavaScript — это язык, а не среда.&lt;/strong&gt; Один и тот же язык работает в браузере, в &lt;a href=&#34;https://hackerx.ru/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-node-js/&#34;&gt;Node.js&lt;/a&gt; и во встраиваемых движках; разное там не он, а доступные API.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;К Java он отношения не имеет.&lt;/strong&gt; Имя — маркетинговый ход 1995 года, когда Java была на пике.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ECMAScript — это стандарт языка.&lt;/strong&gt; JavaScript — его реализация плюс окружение. DOM и &lt;code&gt;window&lt;/code&gt; в стандарт не входят вовсе.&lt;/li&gt;&#xA;&lt;li&gt;«ES6» и «ES2015» — одно и то же. С 2015 года стандарт выходит &lt;strong&gt;раз в год&lt;/strong&gt; и называется по году.&lt;/li&gt;&#xA;&lt;li&gt;Учить сначала JavaScript, потом TypeScript: последний исчезает при сборке, а выполняется всё равно JS.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Установка Go на Ubuntu: официальный способ и почему не apt</title>
      <link>https://hackerx.ru/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B5%D0%B9-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B8-go-%D0%BD%D0%B0-linux-ubuntu/</link>
      <pubDate>Wed, 29 Mar 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B5%D0%B9-%D0%B2%D0%B5%D1%80%D1%81%D0%B8%D0%B8-go-%D0%BD%D0%B0-linux-ubuntu/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Не ставьте Go через &lt;code&gt;apt install golang-go&lt;/code&gt;&lt;/strong&gt; — пакет в репозитории Ubuntu отстаёт от актуальной версии.&lt;/li&gt;&#xA;&lt;li&gt;Правильный способ — &lt;strong&gt;официальный tar-архив с go.dev&lt;/strong&gt;, распакованный в &lt;code&gt;/usr/local/go&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;После распаковки — добавить &lt;code&gt;/usr/local/go/bin&lt;/code&gt; в &lt;code&gt;PATH&lt;/code&gt;, иначе &lt;code&gt;go&lt;/code&gt; не найдётся.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;GOPATH настраивать не нужно:&lt;/strong&gt; с появлением модулей (Go 1.11) он потерял прежнюю роль, зависимости описывает &lt;code&gt;go.mod&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Обновление — удалить старую папку и распаковать новую на то же место.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Команды не запускались на живой Ubuntu — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Даны по официальной документации go.dev. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>ECMAScript 6: что принёс и что было после него</title>
      <link>https://hackerx.ru/ecmascript6/</link>
      <pubDate>Fri, 24 Mar 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/ecmascript6/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;ES6 и ES2015 — одно и то же.&lt;/strong&gt; С 2015 года стандарт выходит &lt;strong&gt;раз в год&lt;/strong&gt; и называется по году; «ES6» осталось разговорным именем.&lt;/li&gt;&#xA;&lt;li&gt;Это был последний &lt;strong&gt;большой скачок&lt;/strong&gt;: &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;, стрелки, классы, промисы, деструктуризация, модули, шаблонные строки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Babel для ES6 больше не нужен&lt;/strong&gt; — все живые браузеры и все LTS-версии Node понимают его давно.&lt;/li&gt;&#xA;&lt;li&gt;Главное про стрелку — &lt;strong&gt;не краткость, а отсутствие своего &lt;code&gt;this&lt;/code&gt;&lt;/strong&gt;. Из-за этого она хороша в колбэках и вредна в методах объекта.&lt;/li&gt;&#xA;&lt;li&gt;После ES6 обновления стали маленькими и ежегодными: &lt;code&gt;async/await&lt;/code&gt; в ES2017, &lt;code&gt;Promise.allSettled&lt;/code&gt; в ES2020, &lt;code&gt;Object.groupBy&lt;/code&gt; в ES2024.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt;, где приводится фактический вывод. Говорим прямо, а не ставим бейдж «проверено» без проверки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>EventEmitter в Node.js: события своими руками</title>
      <link>https://hackerx.ru/nodejs-events-object-eventemitter/</link>
      <pubDate>Fri, 03 Mar 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/nodejs-events-object-eventemitter/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;EventEmitter&lt;/code&gt; — встроенный механизм подписки: одна часть кода объявляет «случилось событие», другая на него реагирует, и они друг о друге не знают.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;emit&lt;/code&gt; вызывает обработчики синхронно&lt;/strong&gt;, прямо в текущем стеке. Это главное заблуждение: события в Node не откладываются на следующий тик.&lt;/li&gt;&#xA;&lt;li&gt;Событие &lt;code&gt;error&lt;/code&gt; — особенное: если на него нет обработчика, &lt;code&gt;emit(&#39;error&#39;)&lt;/code&gt; &lt;strong&gt;бросает исключение&lt;/strong&gt; и валит процесс.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;events.once()&lt;/code&gt; превращает событие в промис — можно писать &lt;code&gt;await&lt;/code&gt;, а не вкладывать колбэки.&lt;/li&gt;&#xA;&lt;li&gt;Больше 10 слушателей на одно событие — предупреждение об утечке. Обычно это забытый &lt;code&gt;off()&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Половина API самой Node построена на событиях: &lt;a href=&#34;https://hackerx.ru/node-js-for-beginners-create-a-http-server/&#34;&gt;HTTP-сервер&lt;/a&gt; эмитит &lt;code&gt;request&lt;/code&gt;, &lt;a href=&#34;https://hackerx.ru/node-js-stream-pipe/&#34;&gt;поток&lt;/a&gt; — &lt;code&gt;data&lt;/code&gt; и &lt;code&gt;end&lt;/code&gt;, &lt;a href=&#34;https://hackerx.ru/node-js-child-process/&#34;&gt;дочерний процесс&lt;/a&gt; — &lt;code&gt;close&lt;/code&gt;, сам &lt;a href=&#34;https://hackerx.ru/node-js-process/&#34;&gt;процесс&lt;/a&gt; — &lt;code&gt;exit&lt;/code&gt;. Всё это один и тот же класс &lt;code&gt;EventEmitter&lt;/code&gt; из модуля &lt;code&gt;node:events&lt;/code&gt;, и его можно использовать в своём коде.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Redis в Node.js: кэш, счётчики, очереди и блокировки</title>
      <link>https://hackerx.ru/redis-%D0%B8-node-js/</link>
      <pubDate>Mon, 30 Jan 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/redis-%D0%B8-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Redis — хранилище в памяти со структурами данных: строки, хеши, списки, множества, рейтинги. Не «просто кэш».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;GET&lt;/code&gt; всегда возвращает строку.&lt;/strong&gt; Записали число 42 — получите &lt;code&gt;&amp;quot;42&amp;quot;&lt;/code&gt;, и &lt;code&gt;42 + значение&lt;/code&gt; даст &lt;strong&gt;&lt;code&gt;4242&lt;/code&gt;&lt;/strong&gt;. Проверено.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;INCR&lt;/code&gt; атомарен&lt;/strong&gt;: 100 параллельных инкрементов дали ровно 100, ни один не потерян. В отличие от «прочитать, прибавить, записать».&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;&lt;code&gt;SET NX&lt;/code&gt; — готовая блокировка&lt;/strong&gt;: первый захват вернул &lt;code&gt;OK&lt;/code&gt;, второй — &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Пайплайн ускоряет в разы&lt;/strong&gt;: 1000 команд по одной — 114 мс, тем же &lt;code&gt;multi&lt;/code&gt; — 8 мс.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Redis чаще всего называют кэшем, и это сильно занижает картину. Кэш — самый простой из его сценариев; на практике он же счётчик, очередь, распределённая блокировка и рейтинг.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Установка Redis на Ubuntu: официальный репозиторий и защита</title>
      <link>https://hackerx.ru/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-redis-%D0%BD%D0%B0-linux-ubuntu/</link>
      <pubDate>Sat, 21 Jan 2017 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-redis-%D0%BD%D0%B0-linux-ubuntu/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Ставьте Redis из &lt;strong&gt;официального репозитория redis.io&lt;/strong&gt;, а не из стандартного apt: тот отстаёт по версии.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Три настройки по умолчанию раньше приводили к взлому:&lt;/strong&gt; слушал все интерфейсы, без пароля, без ограничений команд.&lt;/li&gt;&#xA;&lt;li&gt;Правило: &lt;strong&gt;&lt;code&gt;bind 127.0.0.1&lt;/code&gt;, сильный пароль (&lt;code&gt;requirepass&lt;/code&gt;), доступ по сети — только когда действительно нужен&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Проверка запуска — &lt;code&gt;redis-cli ping&lt;/code&gt; должен ответить &lt;code&gt;PONG&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Redis без пароля, доступный из интернета, находят автоматические сканеры &lt;strong&gt;за часы&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Команды не запускались на живой Ubuntu — в отличие от &lt;a href=&#34;https://hackerx.ru/redis-%D0%B8-node-js/&#34;&gt;самого разбора Redis&lt;/a&gt;, где мы поднимали настоящий сервер и приводили вывод. Команды установки даны по документации redis.io. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>Middleware в Node.js: как устроена цепочка обработчиков</title>
      <link>https://hackerx.ru/connect-middleware-framework-for-node-js/</link>
      <pubDate>Sat, 31 Dec 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/connect-middleware-framework-for-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Middleware — это функция в цепочке&lt;/strong&gt;, через которую проходит каждый запрос: логирование, авторизация, разбор тела — каждая делает одно.&lt;/li&gt;&#xA;&lt;li&gt;Каждая функция либо передаёт запрос дальше через &lt;strong&gt;&lt;code&gt;next()&lt;/code&gt;&lt;/strong&gt;, либо завершает его ответом. Забыли &lt;code&gt;next()&lt;/code&gt; — запрос &lt;strong&gt;завис&lt;/strong&gt; навсегда.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Порядок критичен:&lt;/strong&gt; middleware выполняются сверху вниз. Авторизация — до выдачи данных, разбор тела — до чтения тела.&lt;/li&gt;&#xA;&lt;li&gt;Обработчик ошибок отличается &lt;strong&gt;числом аргументов&lt;/strong&gt;: &lt;code&gt;(err, req, res, next)&lt;/code&gt; вместо &lt;code&gt;(req, res, next)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Connect как библиотека мёртв, но его модель жива&lt;/strong&gt; — на ней построен Express и весь современный Node-веб.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Примеры не запускались — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом. Код дан по документации Connect и Express. Говорим прямо, а не ставим бейдж «проверено».&lt;/p&gt;</description>
    </item>
    <item>
      <title>readFile или readFileSync: чем синхронное чтение вредит серверу</title>
      <link>https://hackerx.ru/fs-readfile-and-fs-readfilesync/</link>
      <pubDate>Sat, 03 Dec 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/fs-readfile-and-fs-readfilesync/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;readFileSync&lt;/code&gt; останавливает &lt;strong&gt;весь процесс&lt;/strong&gt; до конца чтения. В нашем замере при чтении файла на 117 МБ таймер, обязанный тикать каждые 10 мс, не сработал &lt;strong&gt;ни разу&lt;/strong&gt;: событийный цикл стоял 269 мс.&lt;/li&gt;&#xA;&lt;li&gt;Асинхронный &lt;code&gt;readFile&lt;/code&gt; за то же чтение цикл не блокировал — таймер работал штатно.&lt;/li&gt;&#xA;&lt;li&gt;Правило: &lt;code&gt;Sync&lt;/code&gt; допустим только до старта сервера (конфиг, CLI-скрипты) и запрещён внутри обработчика запроса.&lt;/li&gt;&#xA;&lt;li&gt;Современная форма — &lt;code&gt;await readFile()&lt;/code&gt; из &lt;code&gt;node:fs/promises&lt;/code&gt;, а не колбэк.&lt;/li&gt;&#xA;&lt;li&gt;Без указания кодировки оба метода возвращают &lt;code&gt;Buffer&lt;/code&gt;, а не строку.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;У модуля &lt;code&gt;fs&lt;/code&gt; почти каждая функция существует в двух вариантах: &lt;code&gt;readFile&lt;/code&gt; и &lt;code&gt;readFileSync&lt;/code&gt;, &lt;code&gt;writeFile&lt;/code&gt; и &lt;code&gt;writeFileSync&lt;/code&gt;. Синхронный короче и не требует ни &lt;code&gt;await&lt;/code&gt;, ни колбэка — и именно поэтому его тянут туда, где он ломает сервер.&lt;/p&gt;</description>
    </item>
    <item>
      <title>MySQL и Node.js: подключение, пул и защита от инъекций</title>
      <link>https://hackerx.ru/mysql-node-js-connect-to-database/</link>
      <pubDate>Mon, 28 Nov 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/mysql-node-js-connect-to-database/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Драйвер по умолчанию в 2026 — &lt;strong&gt;&lt;code&gt;mysql2&lt;/code&gt;&lt;/strong&gt;, а не оригинальный &lt;code&gt;mysql&lt;/code&gt;: тот почти не развивается. API совместим, промисы из коробки.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Берите пул, а не одиночное соединение.&lt;/strong&gt; Одно соединение выполняет запросы по очереди и не восстанавливается после обрыва.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Никогда не склеивайте SQL строками.&lt;/strong&gt; Параметры через &lt;code&gt;?&lt;/code&gt; — единственная надёжная защита от инъекций: данные не попадают в текст запроса вообще.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;execute&lt;/code&gt; вместо &lt;code&gt;query&lt;/code&gt; для повторяющихся запросов: сервер разбирает SQL один раз и кэширует план.&lt;/li&gt;&#xA;&lt;li&gt;Обрыв соединения — норма, а не исключение: MySQL закрывает простаивающие соединения сам. Пул это переживает, одиночное — нет.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Подключить MySQL к Node — задача на пять строк. Проблемы начинаются на шестой: когда соединение обрывается, когда запросов становится много и когда в запрос попадает то, что ввёл пользователь.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Модуль fs в Node.js: работа с файлами и каталогами</title>
      <link>https://hackerx.ru/modul-fs-rabota-s-faylami-v-node-js/</link>
      <pubDate>Sun, 22 May 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/modul-fs-rabota-s-faylami-v-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;fs&lt;/code&gt; — встроенный модуль, ставить ничего не нужно. Импортируйте с префиксом: &lt;code&gt;node:fs/promises&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;У модуля &lt;strong&gt;три API одной и той же операции&lt;/strong&gt;: промисы, синхронный и колбэчный. По умолчанию берите промисы.&lt;/li&gt;&#xA;&lt;li&gt;Ошибки различайте по &lt;code&gt;err.code&lt;/code&gt; (&lt;code&gt;ENOENT&lt;/code&gt;, &lt;code&gt;EACCES&lt;/code&gt;, &lt;code&gt;EISDIR&lt;/code&gt;), а не по тексту сообщения: коды стабильны, формулировки меняются.&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;existsSync&lt;/code&gt; перед чтением не нужен и содержит гонку — просто ловите &lt;code&gt;ENOENT&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;В ESM вместо &lt;code&gt;__dirname&lt;/code&gt; используйте &lt;code&gt;import.meta.dirname&lt;/code&gt; (доступен с Node 21.2).&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Модуль &lt;code&gt;fs&lt;/code&gt; — интерфейс Node к файловой системе: чтение, запись, каталоги, права, наблюдение за изменениями. Он встроен в платформу, но у него есть особенность, которая сбивает с толку новичков: &lt;strong&gt;одна и та же операция доступна в трёх разных вариантах&lt;/strong&gt;, и выбор между ними влияет на то, будет ли ваш сервер отвечать другим клиентам.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Sails.js в 2026: жив ли фреймворк и чем его заменить</title>
      <link>https://hackerx.ru/sails-js-mvc-framework-for-node-js/</link>
      <pubDate>Mon, 21 Mar 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/sails-js-mvc-framework-for-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Sails.js — MVC-фреймворк «всё из коробки» для Node.js: роутинг, ORM, WebSocket, генераторы кода одним пакетом.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Он не сломался — его перестали выбирать.&lt;/strong&gt; Экосистема Node пошла путём небольших заменяемых слоёв вместо монолитных фреймворков.&lt;/li&gt;&#xA;&lt;li&gt;Чем заменить, зависит от того, что было нужно: &lt;strong&gt;структура → NestJS&lt;/strong&gt;, &lt;strong&gt;простой HTTP → Express или Fastify&lt;/strong&gt;, &lt;strong&gt;ORM → Prisma или Drizzle&lt;/strong&gt; отдельным слоем.&lt;/li&gt;&#xA;&lt;li&gt;Работающее приложение на Sails переписывать без причины не нужно. Повод — упёрлись в ограничение или не можете нанять людей.&lt;/li&gt;&#xA;&lt;li&gt;Урок общий: в Node фреймворки «всё из коробки» проигрывают не по качеству, а по цене выхода за их модель.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Эта статья была написана в 2016 году как введение в Sails.js — тогда это был живой выбор для тех, кому нужен «Rails для Node». Сегодня она честнее работает как ответ на другой вопрос: &lt;strong&gt;что стало с Sails и что брать вместо него&lt;/strong&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Нотация «большое O»: сложность алгоритмов на практике</title>
      <link>https://hackerx.ru/big-o-notation/</link>
      <pubDate>Tue, 26 Jan 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/big-o-notation/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Big O описывает не время, а его рост&lt;/strong&gt; с размером входа. Это ответ на вопрос «что будет, когда данных станет в тысячу раз больше».&lt;/li&gt;&#xA;&lt;li&gt;Константы и младшие слагаемые отбрасывают: &lt;code&gt;O(2n + 5)&lt;/code&gt; = &lt;code&gt;O(n)&lt;/code&gt;. Важен только характер роста.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Главная практическая пара — O(n²) против O(n).&lt;/strong&gt; Вложенный перебор массива почти всегда сводится к одному проходу с хеш-таблицей.&lt;/li&gt;&#xA;&lt;li&gt;O(1) — доступ по ключу (&lt;code&gt;Map&lt;/code&gt;, объект), O(log n) — деление задачи пополам (бинарный поиск), O(n²) — вложенный цикл.&lt;/li&gt;&#xA;&lt;li&gt;Оценивают обычно &lt;strong&gt;худший случай&lt;/strong&gt; — он даёт гарантию.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;&lt;strong&gt;О проверке кода.&lt;/strong&gt; Оценки сложности — это математика, а не замер: они верны по определению алгоритма. Конкретные времена в статье не измерялись на живой машине, поэтому бейджа «проверено» нет — в отличие от &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;материалов по Node.js&lt;/a&gt; с фактическим выводом.&lt;/p&gt;</description>
    </item>
    <item>
      <title>HTTP-сервер на Node.js: «Hello, World!» без фреймворков</title>
      <link>https://hackerx.ru/node-js-for-beginners-create-a-http-server/</link>
      <pubDate>Thu, 14 Jan 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-js-for-beginners-create-a-http-server/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;HTTP-сервер на Node не требует ни одной зависимости: модуль &lt;code&gt;node:http&lt;/code&gt; встроен в платформу.&lt;/li&gt;&#xA;&lt;li&gt;Минимальный рабочий сервер — пять строк: &lt;code&gt;createServer((req, res) =&amp;gt; res.end(&#39;...&#39;))&lt;/code&gt; плюс &lt;code&gt;server.listen(port)&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Каждый ответ обязан заканчиваться &lt;code&gt;res.end()&lt;/code&gt;. Забыли — браузер будет ждать до таймаута.&lt;/li&gt;&#xA;&lt;li&gt;Для кириллицы обязателен &lt;code&gt;charset=utf-8&lt;/code&gt; в заголовке &lt;code&gt;Content-Type&lt;/code&gt;, иначе вместо текста будут кракозябры.&lt;/li&gt;&#xA;&lt;li&gt;Express нужен не всегда: пока маршрутов несколько, встроенного &lt;code&gt;http&lt;/code&gt; достаточно.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Node.js создавался как способ обрабатывать сетевые запросы, поэтому HTTP-сервер здесь — не библиотека, а часть платформы. Ставить ничего не нужно: модуль &lt;code&gt;node:http&lt;/code&gt; уже есть в дистрибутиве — как и &lt;a href=&#34;https://hackerx.ru/modul-fs-rabota-s-faylami-v-node-js/&#34;&gt;&lt;code&gt;fs&lt;/code&gt;&lt;/a&gt;, и &lt;a href=&#34;https://hackerx.ru/node-js-child-process/&#34;&gt;&lt;code&gt;child_process&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Установка Node.js на Ubuntu: nvm, NodeSource или apt</title>
      <link>https://hackerx.ru/ustanovka-node-js-na-linux-ubuntu-14-04/</link>
      <pubDate>Wed, 06 Jan 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/ustanovka-node-js-na-linux-ubuntu-14-04/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ubuntu 14.04 и 16.04 из старого заголовка этой статьи давно мертвы.&lt;/strong&gt; Актуальные LTS на июль 2026: &lt;strong&gt;26.04 «Resolute Raccoon»&lt;/strong&gt;, &lt;strong&gt;24.04 Noble&lt;/strong&gt; и &lt;strong&gt;22.04 Jammy&lt;/strong&gt;. У 20.04 стандартная поддержка закончилась 31 мая 2025 года.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Не ставьте Node через &lt;code&gt;apt install nodejs&lt;/code&gt;.&lt;/strong&gt; В Ubuntu 24.04 этот пакет даёт &lt;strong&gt;Node 18.19.1&lt;/strong&gt;, а Node 18 снят с поддержки в марте 2025-го: вы установите версию без обновлений безопасности.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для разработки — nvm или fnm&lt;/strong&gt;: несколько версий на машине, переключение одной командой, никакого &lt;code&gt;sudo&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Для сервера — NodeSource&lt;/strong&gt;: системный пакет, обновления через apt. Поддерживает Ubuntu 20.04, 22.04 и 24.04.&lt;/li&gt;&#xA;&lt;li&gt;Ставить сегодня стоит &lt;strong&gt;Node 24 (Krypton)&lt;/strong&gt; — это Active LTS.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Установка Node.js на Ubuntu выглядит как задача на одну команду — и именно поэтому её чаще всего делают неправильно. Первая же команда из поиска ставит версию, снятую с поддержки.&lt;/p&gt;</description>
    </item>
    <item>
      <title>JavaScript: справочник и путь обучения с нуля</title>
      <link>https://hackerx.ru/learn-javascript/</link>
      <pubDate>Fri, 01 Jan 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/learn-javascript/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Справочник по JavaScript на русском: &lt;strong&gt;язык, DOM, работа с элементами, алгоритмы&lt;/strong&gt; — с разбором частых ловушек, а не пересказом документации.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;jQuery-статьи дают нативный аналог&lt;/strong&gt; каждой задачи: библиотека сегодня опциональна, а понимать её код полезно.&lt;/li&gt;&#xA;&lt;li&gt;Сквозная тема раздела — &lt;strong&gt;безопасность фронтенда:&lt;/strong&gt; XSS, экранирование, белые списки. Один принцип в разных задачах.&lt;/li&gt;&#xA;&lt;li&gt;Ниже — &lt;strong&gt;рекомендуемый путь&lt;/strong&gt; для начинающих и &lt;strong&gt;полный индекс по темам&lt;/strong&gt;.&lt;/li&gt;&#xA;&lt;li&gt;Серверный JavaScript, Node.js и базы — в соседнем разделе &lt;a href=&#34;https://hackerx.ru/node-tutorial/&#34;&gt;Node.js&lt;/a&gt;.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;JavaScript — язык, на котором работает почти всё в вебе. Этот раздел собирает то, что нужно знать о нём на практике: не полную документацию, а разбор мест, где ошибаются даже опытные.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Node.js: справочник и путь обучения с нуля</title>
      <link>https://hackerx.ru/node-tutorial/</link>
      <pubDate>Fri, 01 Jan 2016 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/node-tutorial/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;Справочник по Node.js на русском: &lt;strong&gt;от установки до потоков и баз данных&lt;/strong&gt;, с проверенным кодом.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Порядок имеет значение.&lt;/strong&gt; Промисы объясняют, почему всё работает именно так; без них дальше будет непонятно.&lt;/li&gt;&#xA;&lt;li&gt;Обновлённые материалы несут бейдж с версией платформы: &lt;strong&gt;код был запущен&lt;/strong&gt;, в тексте — фактический вывод, а не пересказ документации.&lt;/li&gt;&#xA;&lt;li&gt;Где мы не проверяли — так и написано. Обещаний без покрытия здесь нет.&lt;/li&gt;&#xA;&lt;li&gt;Ниже — &lt;strong&gt;рекомендуемый путь&lt;/strong&gt; для начинающих и &lt;strong&gt;полный индекс по темам&lt;/strong&gt; для тех, кто ищет конкретное.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Node.js — среда, которая запускает JavaScript вне браузера. Этот раздел собирает то, что нужно знать о ней на практике: не пересказ официальной документации, а разбор мест, где обычно ошибаются.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Что такое Node.js и когда его не стоит брать</title>
      <link>https://hackerx.ru/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-node-js/</link>
      <pubDate>Thu, 15 Oct 2015 00:00:00 +0300</pubDate>
      <guid>https://hackerx.ru/%D1%87%D1%82%D0%BE-%D1%82%D0%B0%D0%BA%D0%BE%D0%B5-node-js/</guid>
      <description>&lt;aside class=&#34;tldr&#34; aria-label=&#34;Кратко&#34;&gt;&#xA;  &lt;p class=&#34;tldr-head&#34;&gt;Кратко&lt;/p&gt;&#xA;  &lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;Node.js — не язык, а среда выполнения.&lt;/strong&gt; Язык — JavaScript. Node даёт ему движок V8 и библиотеку libuv, чтобы работать с сетью и файлами вне браузера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Ваш JavaScript выполняется в одном потоке&lt;/strong&gt;, но процесс однопоточным не является: диск и DNS libuv тянет пулом (по умолчанию 4 потока).&lt;/li&gt;&#xA;&lt;li&gt;Один поток — преимущество на ожидании и проблема на вычислениях. Замер: цикл на &lt;strong&gt;234 мс не дал сработать ни одному тику&lt;/strong&gt; 10-мс таймера.&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Выигрывает на вводе-выводе&lt;/strong&gt; (API, чаты, прокси, стриминг), &lt;strong&gt;проигрывает на вычислениях&lt;/strong&gt; (видео, ML).&lt;/li&gt;&#xA;&lt;li&gt;В 2026 в платформу встроены &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;WebSocket&lt;/code&gt;, &lt;code&gt;crypto&lt;/code&gt;, тест-раннер и разбор аргументов — половина того, ради чего раньше ставили пакеты.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;/aside&gt;&#xA;&#xA;&lt;p&gt;Node.js — самый частый ответ на вопрос «на чём писать бэкенд, если фронтенд на JavaScript». Разберёмся, что это на самом деле, за счёт чего работает и где ломается.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Воскан Восканян</title>
      <link>https://hackerx.ru/author/voskan/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://hackerx.ru/author/voskan/</guid>
      <description>&lt;p&gt;Воскан Восканян — автор всех материалов блога HackerX. Статьи публиковались с октября 2015 по июль 2018 года.&lt;/p&gt;&#xA;&lt;h2 id=&#34;о-чём-пишет-автор&#34;&gt;О чём пишет автор&lt;/h2&gt;&#xA;&lt;p&gt;Основная специализация — &lt;strong&gt;серверный JavaScript&lt;/strong&gt;. Больше половины материалов блога посвящены Node.js: от запуска первого HTTP-сервера до работы с потоками, дочерними процессами, промисами и публикации собственных модулей в NPM.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Контакты</title>
      <link>https://hackerx.ru/contacts/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://hackerx.ru/contacts/</guid>
      <description>&lt;p&gt;Пишите, если нашли ошибку в материале, хотите уточнить пример кода, предложить тему для разбора или обсудить сотрудничество. Читаем всё, отвечаем на письма по существу — без шаблонных отписок.&lt;/p&gt;</description>
    </item>
    <item>
      <title>О блоге</title>
      <link>https://hackerx.ru/about-me/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://hackerx.ru/about-me/</guid>
      <description>&lt;p&gt;&lt;strong&gt;HackerX&lt;/strong&gt; — блог о программировании на русском языке. Здесь собраны практические уроки с примерами кода: серверный JavaScript на Node.js, клиентский JavaScript и jQuery, базы данных MongoDB, Redis и MySQL, а также основы теории алгоритмов.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
