<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mari Kalyuzhna</title>
    <description>The latest articles on DEV Community by Mari Kalyuzhna (@mari_banana).</description>
    <link>https://dev.to/mari_banana</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1227511%2Fc51b4597-d77d-4d86-99c2-e3b73c04906d.jpeg</url>
      <title>DEV Community: Mari Kalyuzhna</title>
      <link>https://dev.to/mari_banana</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mari_banana"/>
    <language>en</language>
    <item>
      <title>✨♻️ Визуализируя JavaScript. Часть 2/7: цикл событий [перевод]</title>
      <dc:creator>Mari Kalyuzhna</dc:creator>
      <pubDate>Wed, 06 Dec 2023 16:35:28 +0000</pubDate>
      <link>https://dev.to/mari_banana/vizualiziruia-javascript-2-tsikl-sobytii-pierievod-3a09</link>
      <guid>https://dev.to/mari_banana/vizualiziruia-javascript-2-tsikl-sobytii-pierievod-3a09</guid>
      <description>&lt;p&gt;Данный текст является переводом оригинальной статьи &lt;strong&gt;&lt;a href="https://dev.to/lydiahallie/javascript-visualized-event-loop-3dif"&gt;✨♻️ JavaScript Visualized: Event Loop&lt;/a&gt;&lt;/strong&gt; авторства ****&lt;a href="https://dev.to/lydiahallie"&gt;Lydia Hallie&lt;/a&gt;. В процессе адаптации на русский язык я попыталась сохранить стиль автора.&lt;/p&gt;

&lt;p&gt;Статья является частью серии из 7-ми текстов, в которой Лидия доступно, с живыми иллюстрациями и юмором, раскрывает одни из самых базовых и, вместе с тем, сложных для понимания концепций и принципов JavaScript.&lt;/p&gt;

&lt;h1&gt;
  
  
  Введение
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;«О боже, цикл событий»&lt;/em&gt; — так наверняка думал хотя бы раз в своей жизни любой frontend–разработчик. Это одна из тех вещей, с которыми так или иначе приходится сталкиваться каждому JavaScript разработчику чуть ли не каждый день, но поначалу концепция Event Loop кажется запутанной. Я визуал и умею наглядно представлять информацию, поэтому решила попытаться помочь вам, объяснив это визуально с помощью гифок с низким разрешением, потому что на дворе 2019 год [на момент написания оригинального поста], а гифки почему-то все еще пиксельные и размытые.&lt;/p&gt;

&lt;p&gt;Но прежде всего, что такое цикл событий и почему вас это должно волновать?&lt;/p&gt;

&lt;p&gt;JavaScript является &lt;strong&gt;однопоточным&lt;/strong&gt; : одновременно может выполняться только одна задача. Обычно в этом нет ничего страшного, но теперь представьте, что вы выполняете задачу, которая занимает 30 секунд... М-да... Во время этой задачи мы ждем 30 секунд, прежде чем что-то еще может произойти (JavaScript по умолчанию запускается в основном потоке браузера, поэтому весь интерфейс завис) 😬 На дворе 2019 год, никому не нужен медленный и не отвечающий сайт.&lt;/p&gt;

&lt;p&gt;К счастью, браузер предоставляет нам некоторые функции, которых нет в самом движке JavaScript: Web API. Сюда входят DOM API, &lt;code&gt;setTimeout&lt;/code&gt;, HTTP-запросы и т. д. Это может помочь нам создать асинхронное, поведение, которое не будет блокировать основной поток 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  Стек вызовов
&lt;/h1&gt;

&lt;p&gt;Когда мы вызываем функцию, она добавляется в нечто, называемое стеком вызовов (call stack). Стек вызовов является частью движка JS и не зависит от браузера. Это очередь, что означает “первый пришёл, последний ушёл” (представьте себе стопку блинов). Когда функция возвращает значение, оно извлекается из стека 👋&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Стек вызовов — это структура данных, которая, говоря упрощённо, записывает сведения о месте в программе, где мы находимся. Если мы переходим в функцию, мы помещаем запись о ней в верхнюю часть стека. Когда мы из функции возвращаемся, мы вытаскиваем из стека самый верхний элемент и оказываемся там, откуда вызывали эту функцию. Это — всё, что умеет стек.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fburh7kug5g07ibtyogjx.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fburh7kug5g07ibtyogjx.gif" alt="1 || Функции помещаются в стек вызовов, когда мы их вызываем, и извлекаются, когда возвращают какой-то результат"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1 || Функции помещаются в стек вызовов, когда мы их вызываем, и извлекаются, когда возвращают какой-то результат&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Очередь вызовов и setTimeout
&lt;/h1&gt;

&lt;p&gt;Функция &lt;code&gt;respond&lt;/code&gt; возвращает &lt;code&gt;setTimeout&lt;/code&gt; функцию. &lt;code&gt;setTimeout&lt;/code&gt; предоставляется Web API: он позволяет нам откладывать задачи на заданное время, не блокируя основной поток. Функция обратного вызова (коллбэк), которую мы передали функции &lt;code&gt;setTimeout&lt;/code&gt;, стрелочная функция &lt;code&gt;() =&amp;gt; { return 'Hey'}&lt;/code&gt;, добавляется в Web API. Тем временем &lt;code&gt;setTimeout&lt;/code&gt; функция и функция &lt;code&gt;respond&lt;/code&gt; извлекаются из стека, они обе вернули свои значения!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca3pgjj89ewbq012l1zh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fca3pgjj89ewbq012l1zh.gif" alt="2 || setTimeout предоставляется нам со стороны браузера, Web API позаботится о коллбэке, который мы передали"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2 || setTimeout предоставляется нам со стороны браузера, Web API позаботится о коллбэке, который мы передали&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;В Web API таймер работает столько, сколько мы указали во втором аргументе, — 1000 мс (по умолчанию время в JS указывается в мс). Коллбэк не добавляется сразу в стек вызовов, вместо этого он откладывается в нечто, называемое очередью.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz1dn6e31uede9lexocc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqz1dn6e31uede9lexocc.gif" alt="3 || Когда время таймера закончится (1000 мс, в данном случае), коллбэк будет помещён в очередь вызовов"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3 || Когда время таймера закончится (1000 мс, в данном случае), коллбэк будет помещён в очередь вызовов&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Это может сбить с толку: окончание таймера не означает, что функция обратного вызова добавляется в стек вызовов (и, следовательно, возвращает значение) через 1000 мс! Коллбэк просто добавляется в &lt;em&gt;очередь&lt;/em&gt; через 1000 мс. Но это очередь, функция должна дождаться своей очереди!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Очереди работают по принципу “первый пришёл, первый вышел” (представьте себе очередь в магазине).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Наконец, часть, которую мы все ждали… Пришло время циклу событий выполнить свою единственную задачу: &lt;strong&gt;соединить очередь со стеком вызовов&lt;/strong&gt;! Если стек вызовов &lt;strong&gt;пуст&lt;/strong&gt;, т. е. все ранее вызванные функции вернули свои значения и были извлечены из стека, &lt;em&gt;первый элемент&lt;/em&gt; из очереди добавляется в стек вызовов. В этом случае никакие другие функции не вызывались, а это означает, что стек вызовов был пуст к тому моменту, когда функция обратного вызова стала первым элементом в очереди.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc1q8yf1hapxinsghxjg.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc1q8yf1hapxinsghxjg.gif" alt="4 || Цикл событий смотрит на очередь коллбэков и на стек вызовов. Есть стек вызовов пуст, в него перемещается первый элемент из очереди коллбэков"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4 || Цикл событий смотрит на очередь коллбэков и на стек вызовов. Есть стек вызовов пуст, в него перемещается первый элемент из очереди коллбэков&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Наконец, коллбэк добавляется в стек вызовов, вызывается, возвращает значение и извлекается из стека. Ура! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0t1d0ivuj5trbo8ip4k.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0t1d0ivuj5trbo8ip4k.gif" alt="5 || Коллбэк добавляется в стек вызовов и выполняется. После того, как функция возвращает значение, они извлекается из стека вызовов"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5 || Коллбэк добавляется в стек вызовов и выполняется. После того, как функция возвращает значение, они извлекается из стека вызовов&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Читать статью весело, но вам станет комфортно со стеком вызовов только тогда, когда будете работать с ним снова и снова. Попытайтесь выяснить, что выведется в консоль, если мы запустим следующей код:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Second&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baz&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Third&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;baz&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Разобрались? Давайте быстро взглянем, что происходит, “за кулисами” когда мы запускаем этот код в браузере:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fif6tkd11i81x4b835q9s.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fif6tkd11i81x4b835q9s.gif" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Мы вызываем &lt;code&gt;bar&lt;/code&gt;.&lt;code&gt;bar&lt;/code&gt; возвращает таймер &lt;code&gt;setTimeout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Коллбэк, который мы передали в &lt;code&gt;setTimeout&lt;/code&gt;, добавляется в Web API, функции &lt;code&gt;setTimeout&lt;/code&gt; и &lt;code&gt;bar&lt;/code&gt; извлекаются из стека вызовов.&lt;/li&gt;
&lt;li&gt;Таймер запускается, тем временем &lt;code&gt;foo&lt;/code&gt; вызывается и логирует &lt;code&gt;First&lt;/code&gt;. &lt;code&gt;foo&lt;/code&gt; возвращает &lt;code&gt;*undefined*&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Вызывается &lt;code&gt;baz&lt;/code&gt; и попадает в стек вызовов, тем временем, коллбэк таймера добавляется в очередь. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;baz&lt;/code&gt; логирует &lt;code&gt;Third&lt;/code&gt;. Цикл событий видит, что стек вызовов пустеет после того, как из  &lt;code&gt;baz&lt;/code&gt; возвращается &lt;code&gt;*undefined*&lt;/code&gt;. Теперь коллбэк таймера добавляется в стек вызовов.&lt;/li&gt;
&lt;li&gt;Наконец, логируется &lt;code&gt;Second&lt;/code&gt;. Коллбэк отработал, вернул &lt;code&gt;*undefined*&lt;/code&gt; и вышел из стека вызовов.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Заключение
&lt;/h1&gt;

&lt;p&gt;Надеюсь, что благодаря этому посту вы почувствуете себя более комфортно с циклом событий! Не волнуйтесь, если это все еще кажется запутанным, самое главное — &lt;strong&gt;понять, откуда могут возникнуть определенные ошибки/поведение,&lt;/strong&gt; чтобы &lt;strong&gt;эффективно находить в Google нужные термины&lt;/strong&gt; и, в конечном итоге, оказаться на правильной странице Stack Overflow 💪🏼 Не стесняйтесь обращаться к автору, если у вас есть вопросы!&lt;/p&gt;







&lt;p&gt;&lt;strong&gt;Lydia Hallie в соцсетях: &lt;a href="https://www.twitter.com/lydiahallie" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; || &lt;a href="https://www.instagram.com/theavocoder" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; || &lt;a href="https://www.github.com/lydiahallie" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; || &lt;a href="https://www.linkedin.com/in/lydia-hallie" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; || &lt;a href="https://www.lydiahallie.io/" rel="noopener noreferrer"&gt;Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Автор использовала &lt;strong&gt;Keynote&lt;/strong&gt; для создания анимаций и записей экрана.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.P.S.&lt;/strong&gt; В других статьях будут рассмотрены такие штуки, как &lt;em&gt;Поднятие&lt;/em&gt; (&lt;em&gt;hoisting&lt;/em&gt;), область действия (scope chain), прототипное наследование (prototypal inheritance), генераторы и итераторы (generators ans iterators), промисы (promises) и async/await.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>learning</category>
      <category>frontend</category>
    </item>
    <item>
      <title>🚀⚙️ Визуализируя JavaScript. Часть 1/7: ядро JavaScript [перевод]</title>
      <dc:creator>Mari Kalyuzhna</dc:creator>
      <pubDate>Wed, 06 Dec 2023 13:55:49 +0000</pubDate>
      <link>https://dev.to/mari_banana/vizualiziruia-javascript-iadro-javascript-pierievod-59ca</link>
      <guid>https://dev.to/mari_banana/vizualiziruia-javascript-iadro-javascript-pierievod-59ca</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oRlonepe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppkrydxpsojm842p2emp.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oRlonepe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ppkrydxpsojm842p2emp.jpeg" alt="Краткая иллюстрация процесса обработки скриптов движком JS" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Краткая иллюстрация процесса обработки скриптов движком JS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Данный текст является переводом оригинальной статьи &lt;strong&gt;&lt;a href="https://dev.to/lydiahallie/javascript-visualized-the-javascript-engine-4cdf"&gt;🚀⚙️ JavaScript Visualized: the JavaScript Engine&lt;/a&gt;&lt;/strong&gt; авторства &lt;strong&gt;&lt;a href="https://dev.to/lydiahallie"&gt;Lydia Hallie&lt;/a&gt;&lt;/strong&gt;. В процессе адаптации на русский язык я попыталась сохранить стиль автора.&lt;/p&gt;

&lt;p&gt;Статья является частью серии из 7-ми текстов, в которой Лидия доступно, с живыми иллюстрациями и юмором, раскрывает одни из самых базовых и, вместе с тем, сложных для понимания концепций и принципов JavaScript.&lt;/p&gt;

&lt;h1&gt;
  
  
  Вступление
&lt;/h1&gt;

&lt;p&gt;JavaScript очень крут (и не только на мой взгляд). Но как, спросите Вы, машина может действительно понимать код, который мы пишем? Нам, JavaScript разработчикам, обычно не приходится иметь дело непосредственно с компиляторами. Однако, неплохо бы иметь базовые представления об устройстве ядра JavaScript и знать, как в нём наш human-friendly код обрабатывается и преобразуется в машинные команды. 🥳&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Внимание!&lt;/strong&gt; Данный пост, в основном, опирается на движок V8, используемый в Node.js и Chromium-подобных браузерах.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Итак. Что же происходит “за кулисами”?&lt;/p&gt;

&lt;h1&gt;
  
  
  Этап 1. Поток байтов
&lt;/h1&gt;

&lt;p&gt;Парсер HTML сталкивается с тэгом &lt;code&gt;script&lt;/code&gt; с указанием источника. Код из этого источника запрашивается из &lt;strong&gt;сети&lt;/strong&gt;, &lt;strong&gt;кэша&lt;/strong&gt; или установленного &lt;strong&gt;сервис воркера&lt;/strong&gt; (&lt;strong&gt;&lt;em&gt;service worker&lt;/em&gt;&lt;/strong&gt;). Ответом на запрос является скрипт, представленный в виде &lt;strong&gt;потока байтов&lt;/strong&gt;. Забота об этом потоке поручается специально обученному &lt;strong&gt;декодеру потока байтов&lt;/strong&gt;, который обрабатывает данные по мере загрузки :)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--L1byt5uG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awm2sg6i16hbz6evxe5q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--L1byt5uG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/awm2sg6i16hbz6evxe5q.gif" alt="1 || Скрипт загружается в виде потока байтов в кодировке UTF-16 из сети, кэша или воркера и передаётся в декодер потока байтов" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;1 || Скрипт загружается в виде потока байтов в кодировке UTF-16 из сети, кэша или воркера и передаётся в декодер потока байтов&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Этап 2. Декодер потока байтов
&lt;/h1&gt;

&lt;p&gt;Декодер потока байтов создаёт специальные &lt;strong&gt;токены&lt;/strong&gt; на основе поступившего потока. Так, например, &lt;code&gt;0066&lt;/code&gt; преобразуется в &lt;code&gt;f&lt;/code&gt;, &lt;code&gt;0075&lt;/code&gt; — в &lt;code&gt;u&lt;/code&gt;, &lt;code&gt;006e&lt;/code&gt; — в &lt;code&gt;n&lt;/code&gt;, &lt;code&gt;0063&lt;/code&gt; — в &lt;code&gt;c&lt;/code&gt;, &lt;code&gt;0074&lt;/code&gt; — в &lt;code&gt;t&lt;/code&gt;, &lt;code&gt;0069&lt;/code&gt; — в &lt;code&gt;i&lt;/code&gt;, &lt;code&gt;006f&lt;/code&gt; — в&lt;code&gt;o&lt;/code&gt;, а &lt;code&gt;006e&lt;/code&gt; превратится в &lt;code&gt;n&lt;/code&gt; с последующим пробелом. Кажется, здесь было закодировано ключевое слово &lt;code&gt;function&lt;/code&gt;! В JavaScript это одно из специальных зарезервированных слов. Итак токен был создан и отправлен в парсер (и &lt;em&gt;препарсер&lt;/em&gt;, что пока не отображено в иллюстрациях, потому что мы вернёмся к этому моменту позже). Похожая судьба постигает и все остальные символы во входящем потоке байтов.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4xXq8NIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfzwadsg94spn9xx8rab.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4xXq8NIF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xfzwadsg94spn9xx8rab.gif" alt="2 || Декодер потока байтов переводит байты в токены. Токены отправляются в парсер" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;2 || Декодер потока байтов переводит байты в токены. Токены отправляются в парсер&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Этап 3. Парсер и Абстрактное Синтаксическое Дерево
&lt;/h1&gt;

&lt;p&gt;Ядро движка на самом деле состоит аж из &lt;em&gt;двух парсеров&lt;/em&gt;: &lt;strong&gt;&lt;em&gt;препарсера&lt;/em&gt;&lt;/strong&gt; (&lt;em&gt;pre-parser&lt;/em&gt;) и &lt;strong&gt;&lt;em&gt;парсера&lt;/em&gt;&lt;/strong&gt; (&lt;em&gt;parser&lt;/em&gt;). В попытках сократить время загрузки веб-сайта, движок старается не парсить код, в котором нет необходимости сразу, прямо сейчас. Препарсер обрабатывает код, который может быть использован позже, в то время как парсер работает над кодом, который нужен “здесь и сейчас”!&lt;/p&gt;

&lt;p&gt;Например, если какая-то функция вызывается только когда пользователь нажимает на кнопку, нет нужды компилировать эту часть кода немедленно для загрузки сайта. А вот, когда пользователь вызовет событие клика по кнопке, запрашивая тем самым конкретную функцию, тогда парсер обработает её.&lt;/p&gt;

&lt;p&gt;Парсер генерирует узлы (ноды), основанные на токенах, полученных из декодера потока байтов. Из этих узлов формируется Абстрактное Синтаксическое Дерево (Abstract Syntax Tree, AST). 🌳&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yJEP3wgQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehifxwob09vvlblxgr98.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yJEP3wgQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ehifxwob09vvlblxgr98.gif" alt="3 || Парсер генерирует узлы, основанные на токенах, и создаёт Абстрактное Синтаксическое Дерево" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;3 || Парсер генерирует узлы, основанные на токенах, и создаёт Абстрактное Синтаксическое Дерево&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Этап 4. Интерпретатор
&lt;/h1&gt;

&lt;p&gt;Наконец, в дело вступает &lt;strong&gt;интерпретатор&lt;/strong&gt;! Интерпретатор, который проходит через AST, и генерирует &lt;strong&gt;байтовый код&lt;/strong&gt;, основанный на информации, полученной от AST. После того, как код сгенерирован полностью, Абстрактное Синтаксическое Дерево удаляется, очищая память. Итак, наконец, мы имеем что-то, с чем может работать наша машина (компьютер/телефон и т.д.)! 🎉&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--IyVUlK5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5ppz6r6mfd0mhmi30xv.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--IyVUlK5s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5ppz6r6mfd0mhmi30xv.gif" alt="4 || Интерпретатор проходится по AST (Абстрактное Синтаксическое Дерево) и генерирует байтовый код" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;4 || Интерпретатор проходится по AST (Абстрактное Синтаксическое Дерево) и генерирует байтовый код&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Этап 5. Оптимизирующий компилятор
&lt;/h1&gt;

&lt;p&gt;Хотя байт-код быстрый, он может быть быстрее. По мере выполнения этого байт-кода генерируется информация. Он может определить, часто ли повторяемся определенное поведение, а также типы используемых данных. Возможно, вы вызываете какую-то функцию десятки раз: пришло время ее оптимизировать, чтобы она работала еще быстрее! 🏃🏽‍♀️&lt;/p&gt;

&lt;p&gt;Байт-код вместе с фидбеком сгенерированного типа отправляется &lt;strong&gt;оптимизирующему компилятору&lt;/strong&gt;. Оптимизирующий компилятор принимает байт-код и фидбэк типа и генерирует на их основе высокооптимизированный машинный код. 🚀&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SFRC3Hhf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd07sii033lrga13380n.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SFRC3Hhf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cd07sii033lrga13380n.gif" alt="5 || Байт–код и фидбек типа отправляются в оптимизирующий компилятор, который генерирует высоко оптимизированный машинный код" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;5 || Байт–код и фидбек типа отправляются в оптимизирующий компилятор, который генерирует высоко оптимизированный машинный код&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Про работу движка с динамической типизацией
&lt;/h1&gt;

&lt;p&gt;JavaScript — это динамически типизированный язык, а это означает, что типы данных могут постоянно меняться. Было бы очень медленно, если бы движку JavaScript приходилось каждый раз проверять, какой тип данных имеет определенное значение.&lt;/p&gt;

&lt;p&gt;Чтобы сократить время, необходимое для интерпретации кода, оптимизированный машинный код обрабатывает только те случаи, которые движок видел раньше при запуске байт-кода. Если мы неоднократно использовали определенный фрагмент кода, который снова и снова возвращал один и тот же тип данных, оптимизированный машинный код можно просто использовать повторно, чтобы ускорить процесс. Однако, поскольку JavaScript является динамически типизированным, может случиться так, что один и тот же фрагмент кода внезапно вернет данные другого типа. Если это произойдет, машинный код будет деоптимизирован, и движок вернется к интерпретации сгенерированного байт-кода.&lt;/p&gt;

&lt;p&gt;Допустим, определенная функция вызывается 100 раз и до сих пор всегда возвращала одно и то же значение. Предполагается , что он также вернет это значение при 101-м вызове.&lt;/p&gt;

&lt;p&gt;Допустим, у нас есть некоторая функция &lt;code&gt;sum&lt;/code&gt;, которая (до сих пор) всегда вызывалась с числовыми значениями в качестве аргументов каждый раз:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Вызов функции в примере выше вернёт число &lt;code&gt;3&lt;/code&gt;! В следующий раз, когда мы вызовем нашу функцию, движок будет считать, что мы вызываем её снова с двумя числовыми значениями.&lt;/p&gt;

&lt;p&gt;Если это правда, динамический поиск не требуется, и можно просто повторно использовать оптимизированный машинный код. В противном случае, если предположение было неверным, вместо оптимизированного машинного кода произойдет возврат к исходному байтовому коду.&lt;/p&gt;

&lt;p&gt;Например, при следующем вызове мы передадим строку вместо числа. Поскольку JavaScript является динамически типизированным, мы можем сделать это без каких-либо ошибок!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;В таком случае, число &lt;code&gt;2&lt;/code&gt; будет преобразовано в строку, и вместо числа 3 функция вернет строку &lt;code&gt;"12"&lt;/code&gt;. Движок JavaScript возвращается к выполнению интерпретированного байт-кода и обновляет обратную связь о типе.&lt;/p&gt;

&lt;h1&gt;
  
  
  Заключение
&lt;/h1&gt;

&lt;p&gt;Надеюсь, этот пост был полезен для вас! Конечно, остаётся ещё много частей ядра JS, которые я не раскрыла в этом материале (JS heap, стек вызовов, и т.д.), о которых я расскажу позже! Я определенно рекомендую вам начать самостоятельно проводить исследования, если вы интересуетесь внутренними особенностями JavaScript. V8 имеет открытый исходный код и имеет отличную документацию о том, как он работает под капотом! 🤖&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Полезные ссылки:&lt;/strong&gt; &lt;a href="https://v8.dev/"&gt;V8 Docs&lt;/a&gt; || &lt;a href="https://github.com/v8/v8"&gt;V8 Github&lt;/a&gt; || &lt;a href="https://www.youtube.com/watch?v=voDhHPNMEzg&amp;amp;t=729s%3Cbr%3E%0A"&gt;Chrome University 2018: Life Of A Script&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ролик на YouTube на английском, где Лидия ещё более наглядно разбирает устройство движка JavaScript: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/xckH5s3UuX4?si=3EpsmOobYqvImos2"&gt;Understanding the V8 JavaScript Engine&lt;/a&gt;&lt;/p&gt;







&lt;p&gt;&lt;strong&gt;Lydia Hallie в соцсетях: &lt;a href="https://www.twitter.com/lydiahallie"&gt;Twitter&lt;/a&gt; || &lt;a href="https://www.instagram.com/theavocoder"&gt;Instagram&lt;/a&gt; || &lt;a href="https://www.github.com/lydiahallie"&gt;GitHub&lt;/a&gt; || &lt;a href="https://www.linkedin.com/in/lydia-hallie"&gt;LinkedIn&lt;/a&gt; || &lt;a href="https://www.lydiahallie.io/"&gt;Website&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S.&lt;/strong&gt; Автор использовала &lt;strong&gt;Keynote&lt;/strong&gt; для создания анимаций и записей экрана.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.P.S.&lt;/strong&gt; В следующих статьях будут рассмотрены такие штуки, как Поднятие (hoisting), Цикл событий (event loop), область действия (scope chain), прототипное наследование (prototypal inheritance), генераторы и итераторы (generators ans iterators), промисы (promises) и async/await&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tutorial</category>
      <category>frontend</category>
      <category>computerscience</category>
    </item>
  </channel>
</rss>
