<?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: Igor Bykov</title>
    <description>The latest articles on DEV Community by Igor Bykov (@igor_bykov).</description>
    <link>https://dev.to/igor_bykov</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%2F453576%2Fb681dbcc-c048-4b2f-8c44-1693611691f6.jpg</url>
      <title>DEV Community: Igor Bykov</title>
      <link>https://dev.to/igor_bykov</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/igor_bykov"/>
    <language>en</language>
    <item>
      <title>The most complex challenge of your career</title>
      <dc:creator>Igor Bykov</dc:creator>
      <pubDate>Wed, 11 May 2022 19:22:12 +0000</pubDate>
      <link>https://dev.to/igor_bykov/the-most-complex-challenge-of-your-career-2d2h</link>
      <guid>https://dev.to/igor_bykov/the-most-complex-challenge-of-your-career-2d2h</guid>
      <description>&lt;p&gt;Hey fellows!&lt;/p&gt;

&lt;p&gt;You know, when you do interviews, people sometimes ask you things like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What's the most complex technical challenge you've ever solved?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think, I even read it somewhere that Elon Musk asks this during interviews as well.&lt;/p&gt;

&lt;p&gt;Now, I'm not about to apply to Tesla (don't think they've plugged TypeScript into that fancy display, did they?), but I never had a clear idea what to answer to that question!&lt;/p&gt;

&lt;p&gt;Please, showcase your examples. Strike me with them, if you wish!&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>programming</category>
      <category>showdev</category>
    </item>
    <item>
      <title>A plain, practical guide on recursion in JS</title>
      <dc:creator>Igor Bykov</dc:creator>
      <pubDate>Thu, 18 Mar 2021 21:47:57 +0000</pubDate>
      <link>https://dev.to/igor_bykov/a-plain-practical-guide-on-recursion-in-js-5g5i</link>
      <guid>https://dev.to/igor_bykov/a-plain-practical-guide-on-recursion-in-js-5g5i</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;A guide to recursion for those who want to know in what cases recursion might be useful &amp;amp; how it could be applied IRL.&lt;/p&gt;

&lt;p&gt;No Big O, algorithms, Fibonacci, word reversing, exponents,  or other arbitrary CS topics. I promise.&lt;/p&gt;

&lt;p&gt;Sorry, no TL;DR.&lt;/p&gt;




&lt;p&gt;Unless you did a computer science course in university, recursion might be one of those concepts that you heard of but never had time to finally find out how that could be useful to you.&lt;/p&gt;

&lt;p&gt;It also just happens so, that in modern day-to-day web development, there seem to be &lt;em&gt;quite a few&lt;/em&gt; cases where recursion is the only possible solution to a particular problem.&lt;/p&gt;

&lt;p&gt;Nevertheless, recursion is an exciting topic that might provide you with several important insights &amp;amp; even change the way you think about programming problems.&lt;/p&gt;

&lt;p&gt;So, yes! That's a &lt;strong&gt;brilliant idea&lt;/strong&gt; to finally &lt;em&gt;understand&lt;/em&gt; the recursion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;Recursion is 1 of &lt;em&gt;just&lt;/em&gt; 2 ways to repeat a process in computer programs.&lt;/p&gt;

&lt;p&gt;The second way is called &lt;em&gt;"iteration"&lt;/em&gt; &amp;amp; you are most probably already pretty familiar with this one. For instance, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for" rel="noopener noreferrer"&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; &amp;amp; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/while" rel="noopener noreferrer"&gt;&lt;code&gt;while&lt;/code&gt;&lt;/a&gt; loops, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" rel="noopener noreferrer"&gt;&lt;code&gt;Array.prototype.map&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach" rel="noopener noreferrer"&gt;&lt;code&gt;Array.prototype.forEach&lt;/code&gt;&lt;/a&gt; are great examples of how iteration works.&lt;/p&gt;

&lt;p&gt;The idea of iteration is simple - go a step at a time and repeat whatever procedure you are provided with on each step.&lt;/p&gt;

&lt;p&gt;Let's see an example:&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="c1"&gt;// A magical structure that repeats whatever&lt;/span&gt;
&lt;span class="c1"&gt;// we need to repeat an arbitrary number of times&lt;/span&gt;
&lt;span class="c1"&gt;// ⬇️&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️ procedure to repeat&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, how does the &lt;code&gt;for&lt;/code&gt; loop works under the hood?&lt;br&gt;
What if for whatever reason we would be about to write our own &lt;code&gt;forLoop&lt;/code&gt; function without using &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;do...while&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; or any other built-in loop?&lt;/p&gt;

&lt;p&gt;As for now, we don't have any tools to do this, hence, this task would only result in a mental block &amp;amp; might seem to be impossible, but hold on! It is possible since we've got &lt;strong&gt;2 ways&lt;/strong&gt; to repeat a process.&lt;/p&gt;

&lt;p&gt;The mental model I find very helpful is the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Recursion is no more than an alternative, more flexible way to repeat a process without writing a loop. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Recursion
&lt;/h2&gt;

&lt;p&gt;One of the primary mental blocks I had in understanding recursion was that it doesn't have any available APIs/special language constructs/built-in functions.&lt;/p&gt;

&lt;p&gt;In the case of iteration, we have loops of all flavours but in the case of recursion, we aren't provided with any built-in solutions. We have to implement it from scratch.&lt;/p&gt;

&lt;p&gt;That might be a blocker for learning, but ultimately this is exactly what makes recursion useful because it gives us total control over when, why &amp;amp; how repetition is performed.&lt;/p&gt;

&lt;p&gt;Let's see some examples! First off, let's &lt;code&gt;console.log&lt;/code&gt; numbers from 0 to 10, exactly the same as we did above with &lt;code&gt;for&lt;/code&gt; loop but &lt;strong&gt;recursively&lt;/strong&gt; this time:&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;printNumbersUpTo10&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// #1 for (let i = 0;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// #2 i &amp;lt;= 10;&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️ procedure to repeat&lt;/span&gt;
    &lt;span class="nf"&gt;printNumbersUpTo10&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// #3 i++)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;printNumbersUpTo10&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There might be some surprising parts (we'll get to them later) but let's first concentrate on similarities between recursive &amp;amp; iterative approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Similarities with iteration
&lt;/h3&gt;

&lt;p&gt;I mapped lines of recursive &lt;code&gt;printNumbersUpTo10&lt;/code&gt; function to equivalent parts of &lt;code&gt;for&lt;/code&gt; loop, let's see them step by step:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On line &lt;code&gt;#1&lt;/code&gt; we declare a variable that we will increment on each &lt;del&gt;iteration&lt;/del&gt; step. So, this line is equivalent to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On line &lt;code&gt;#2&lt;/code&gt; we set a condition that will check on each &lt;del&gt;iteration&lt;/del&gt; step whether we are already done or there are more steps to perform. In recursive functions this condition has a special name, it's called "base case". So, this line is equivalent to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;On line &lt;code&gt;#3&lt;/code&gt; we increment our counter variable. So, this line is equivalent to:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In spite of having a lot in common, recursion &amp;amp; iteration differ in several important aspects. To understand those differences, let's discuss in detail how recursion works.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does recursion work?
&lt;/h3&gt;

&lt;p&gt;From any JavaScript engine's point of view, recursion is simply a situation when a function calls itself. &lt;/p&gt;

&lt;p&gt;To see what this means, let's refactor our &lt;code&gt;printNumbersUpTo10&lt;/code&gt; function from the previous example. Let's say we decided that &lt;code&gt;printNumbersUpTo10&lt;/code&gt; is too specific, so, we want a more generic &lt;code&gt;printNumbersUpTo&lt;/code&gt; function that will accept 1 argument - the highest number it should print.&lt;/p&gt;

&lt;p&gt;So, when we will call &lt;code&gt;printNumbersUpTo(5)&lt;/code&gt; it should &lt;code&gt;console.log&lt;/code&gt; numbers from 0 to 5.&lt;/p&gt;

&lt;p&gt;Our first attempt to implement this could look something like this:&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;printNumbersUpTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;printNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ⬅️ this line makes it tick&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;printNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ➡️ logs 5, 4, 3, 2, 1, 0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, we've got a couple of problems here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Numbers are printed 5 to 0 instead of 0 to 5.&lt;/li&gt;
&lt;li&gt;We have to make an additional unnecessary step just to print 0 because our &lt;code&gt;console.log&lt;/code&gt; statement is placed next to &lt;code&gt;printNumbersUpTo&lt;/code&gt; call which makes &lt;code&gt;printNumbersUpTo&lt;/code&gt; call itself one additional time when &lt;code&gt;num&lt;/code&gt; is 0 (-1 is not logged because it fails the check inside the &lt;code&gt;if&lt;/code&gt; statement).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's try to get rid of both problems. A better solution could be something like this:&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;printNumbersUpTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;printNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;printNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ➡️ logs 0, 1, 2, 3, 4, 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you notice how moving &lt;code&gt;console.log&lt;/code&gt; below the &lt;code&gt;printNumbersUpTo(num - 1)&lt;/code&gt; call changed the logging sequence from 5 ➡️ 0 to 0 ➡️ 5?&lt;/p&gt;

&lt;p&gt;It worked this way because when a JS compiler gets to &lt;code&gt;printNumbersUpTo(num - 1)&lt;/code&gt; it starts executing it straight away, then it sees &lt;code&gt;printNumbersUpTo(num - 1)&lt;/code&gt; again and starts executing it, and so on.&lt;/p&gt;

&lt;p&gt;As a result, the compiler first goes all the way &lt;em&gt;in&lt;/em&gt; to the call where &lt;code&gt;num&lt;/code&gt; finally equals 0. When &lt;code&gt;num&lt;/code&gt; is 0, the condition inside of the &lt;code&gt;if&lt;/code&gt; statement is false, so, the &lt;code&gt;if&lt;/code&gt; statement is skipped &amp;amp; the &lt;code&gt;console.log&lt;/code&gt; is executed.&lt;/p&gt;

&lt;p&gt;There's nothing after &lt;code&gt;console.log&lt;/code&gt;, so the compiler finishes with the innermost function &amp;amp; then starts to get back &lt;em&gt;out&lt;/em&gt; to the outermost scope.&lt;/p&gt;

&lt;p&gt;You can see &lt;a href="http://latentflip.com/loupe/?code=ZnVuY3Rpb24gcHJpbnROdW1iZXJzVXBUbyAobnVtKSB7CiAgaWYgKG51bSA%2BIDApIHsKICAgIHByaW50TnVtYmVyc1VwVG8obnVtIC0gMSk7CiAgfQoKICBjb25zb2xlLmxvZyhudW0pOwp9CgpwcmludE51bWJlcnNVcFRvKDUpOw%3D%3D!!!PGJ1dHRvbj5DbGljayBtZSE8L2J1dHRvbj4%3D" rel="noopener noreferrer"&gt;a visualization of this process&lt;/a&gt; using a wonderful tool called "Loupe" built by &lt;a href="https://github.com/latentflip" rel="noopener noreferrer"&gt;Philip Roberts&lt;/a&gt;. Here is the preview:&lt;br&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%2Fiioqkayo62oabtfb1lih.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%2Fiioqkayo62oabtfb1lih.gif" alt="recursive_calls"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To make it even clearer, let's replace each recursive &lt;code&gt;printNumbersUpTo(num - 1)&lt;/code&gt; call with the content of the &lt;code&gt;printNumbersUpTo&lt;/code&gt; function in order to visualize how a JS compiler sees &amp;amp; executes it.&lt;/p&gt;

&lt;p&gt;This is what recursion looks like:&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;printNumbersUpToVisualized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
               &lt;span class="c1"&gt;// this is never executed since&lt;/span&gt;
               &lt;span class="c1"&gt;// num is already 0 here and the&lt;/span&gt;
               &lt;span class="c1"&gt;// condition is false&lt;/span&gt;
            &lt;span class="p"&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="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&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="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&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="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&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="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&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="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;printNumbersUpToVisualized&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 2 most important ideas here are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Recursion is about stacking up function calls on top of each other until the desired condition is met.&lt;/li&gt;
&lt;li&gt;The order of execution is important and with recursion, we have complete control over it.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How recursion is different from iteration?
&lt;/h3&gt;

&lt;p&gt;Due to the fact that we completely control the order of execution (since we can place recursive calls anywhere), the recursive approach allows more flexibility &amp;amp; let us do things that are hard to achieve using loops.&lt;/p&gt;

&lt;p&gt;For instance, let's take a quick look at this example:&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;mirrorNumbersUpTo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;mirrorNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&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="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;mirrorNumbersUpTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ➡️ logs 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We modified &lt;code&gt;printNumbersUpTo&lt;/code&gt; just a slight bit in order to make it mirror numbers. Even in this simple case, it'd be more problematic to implement this same functionality inside a &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;In fact, &lt;code&gt;mirrorNumbersUpTo&lt;/code&gt; is equivalent to a loop that first decrements the number down to 0 (&lt;code&gt;for (let i = 5; 0 &amp;lt;= i; i--)&lt;/code&gt;) and then increments a variable from 1 until it equals the initially provided value (&lt;code&gt;for (let i = 1; i &amp;lt;= 5; i++)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;At this point, one could say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ok, wonderful, but is there a single real-world scenario in which a programmer is &lt;strong&gt;not&lt;/strong&gt; satisfied with the way a &lt;code&gt;for&lt;/code&gt; loop runs?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see!&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical use cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Normalizing arbitrary data structures
&lt;/h3&gt;

&lt;p&gt;In modern JS we have something called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat" rel="noopener noreferrer"&gt;Array.prototype.flat&lt;/a&gt; which is a function that can flatten nested arrays given how deep a nested array structure should be flattened.&lt;/p&gt;

&lt;p&gt;While it's valid to call it like this:&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="nx"&gt;nestedArrays&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in order to flatten an array completely (so, it contains no nested arrays), it is considered a bad practice to do so.&lt;/p&gt;

&lt;p&gt;So, a possible workaround might look like this tiny recursive function &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat#reduce_concat_isarray_recursivity" rel="noopener noreferrer"&gt;adapted from one of the examples on MDN site&lt;/a&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;flatToBase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accumulator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&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;accumulator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nf"&gt;flatToBase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;flatToBase&lt;/span&gt;&lt;span class="p"&gt;([[[[[[[&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;]]]],&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;]]]);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; [ 42, 36 ] &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Traversing arbitrary data structures
&lt;/h3&gt;

&lt;p&gt;Let's say we're building a browser extension that collects &amp;amp; shows some general statistics about the current HTML page.&lt;/p&gt;

&lt;p&gt;For instance, we want to show our users how many HTML tags of each type we have on the current page, how deep the average tag is located, what is the most deeply located tag and so on.&lt;/p&gt;

&lt;p&gt;In order to achieve this, we will obviously need to traverse the entire DOM structure element by element. If we try to use iteration to achieve this task, things get hard from the start. As the first step we could get all children of an element, for instance with something like this:&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;bodyChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;bodyChildren&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// So... how do we get children of each body child?&lt;/span&gt;
  &lt;span class="nf"&gt;analyseElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bodyChildren&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But what do we do after we have iterated over each direct child of &lt;code&gt;body&lt;/code&gt;? Each direct child might have children as well, its children might have children and so on. We will not be able to write enough loops.&lt;/p&gt;

&lt;p&gt;In situations like this, when the data structure we're working on is not known beforehand or is simply too nested, recursion is frequently the only approach we can use. So, let's do a quick prototype of the function that will recursively traverse all HTML elements on the page.&lt;/p&gt;

&lt;p&gt;In this example, we are not going to analyse elements in any way, just traverse all of them &amp;amp; stringify the DOM structure in order to see that our function works fine.&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;traverseHtmlElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_level&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get all element's children stringified if any&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rootChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;childElementCount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rootChildren&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;traverseHtmlElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstElementChild&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_level&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Get all element's siblings stringified if any&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;rootSiblings&lt;/span&gt; &lt;span class="o"&gt;=&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;nextSibling&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextElementSibling&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextSibling&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;rootSiblings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;traverseHtmlElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextSibling&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_level&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// The recursive part is already done above. All code&lt;/span&gt;
  &lt;span class="c1"&gt;// below is just to print HTML structure in a pretty way. &lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ident&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;  &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_level&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;tagName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&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;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&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;classList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&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;rootId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;` id="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt; &lt;span class="p"&gt;:&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;rootClasses&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;classList&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;` class="&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Assemble tags with no children&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;rootChildren&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="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;rootId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;rootClasses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; /&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;rootSiblings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Assemble tags with children&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;rootId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;rootClasses&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;rootChildren&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;ident&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`&amp;lt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tagName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;rootSiblings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&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;stringifiedHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;traverseHtmlElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&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="nx"&gt;stringifiedHTML&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Processing data structures of arbitrary depth
&lt;/h3&gt;

&lt;p&gt;Let's say we are building a web forum where people could discuss things, post images &amp;amp; leave comments about nearly anything they wish.&lt;/p&gt;

&lt;p&gt;Frequently forums don't put any restrictions on conversations' depth, which basically means that any comment might have a sub-comment that might have a sub-comment that might have yet another sub-comment &amp;amp; so on. The simplified data structure that we receive from BE would look something like this:&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
          &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 6&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
            &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 7&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 9&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;}],&lt;/span&gt;
        &lt;span class="p"&gt;}]&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;comment 10&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;comments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's prove we can print it prettily using recursion:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/snowy-platform-lyes1"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;printComment&lt;/code&gt; function from the example above is fairly similar to &lt;code&gt;traverseHtmlElement&lt;/code&gt;, you could notice that all the children/sibling wording already sounds pretty familiar. That's no surprise since those 2 functions do almost the same thing.&lt;/p&gt;

&lt;p&gt;Did you notice that small &lt;code&gt;getArrayIterator&lt;/code&gt; generator function that we used as a helper?&lt;br&gt;
I used it because unlike DOM elements that have the &lt;code&gt;nextElementSibling&lt;/code&gt; property, arrays don't provide a way to go to the next element from the current one.&lt;/p&gt;

&lt;p&gt;In order to avoid reinventing the wheel, we can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator" rel="noopener noreferrer"&gt;generators&lt;/a&gt; that provide a very handy way to go to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next" rel="noopener noreferrer"&gt;&lt;code&gt;next&lt;/code&gt;&lt;/a&gt; step &amp;amp; define whether the iteration is already &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator/next#return_value" rel="noopener noreferrer"&gt;&lt;code&gt;done&lt;/code&gt;&lt;/a&gt; or not within a recursive function.&lt;/p&gt;
&lt;h3&gt;
  
  
  4. Arbitrary depth currying
&lt;/h3&gt;

&lt;p&gt;This example is heavily inspired by &lt;a href="https://javascript.info/currying-partials" rel="noopener noreferrer"&gt;an awesome article&lt;/a&gt; on amazing &lt;a href="https://javascript.info/" rel="noopener noreferrer"&gt;javascript.info&lt;/a&gt;. If you've never heard of it, I'd strongly recommend you to check it out.&lt;/p&gt;

&lt;p&gt;For the sake of simplicity, we will write a pretty simple &lt;code&gt;sum&lt;/code&gt; function. I must admit that, unlike other examples, this example can barely be useful IRL even theoretically, however, the concept it demonstrates is too interesting to omit.&lt;/p&gt;

&lt;p&gt;Let's consider that we want to create a function called &lt;code&gt;sum&lt;/code&gt; that sums up all numbers we feed it. Sounds trivial, however, we want our function to work with pretty much any call signature, so, all these signatures must be valid:&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="nf"&gt;sum&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;1&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;5&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;12&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;132&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&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;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;5&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;1&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&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;span class="mi"&gt;3&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;span class="mi"&gt;2&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It turns out that we can solve this puzzle with recursion quite easily. The trick is to apply it a little bit differently this time.&lt;/p&gt;

&lt;p&gt;The implementation could look something like this:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/kind-ellis-zuqn7"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The most interesting part here is that &lt;code&gt;sumOnce&lt;/code&gt; &lt;em&gt;returns&lt;/em&gt; itself without &lt;em&gt;invoking&lt;/em&gt; itself as long as any argument is supplied.&lt;/p&gt;

&lt;p&gt;This makes &lt;code&gt;sumOnce&lt;/code&gt; a recursive function despite the fact that the invocation part is now delegated to users of this function.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Creating a higher-level abstraction
&lt;/h3&gt;

&lt;p&gt;Sometimes, the iterative approach might help to abstract things out making code cleaner, more organized &amp;amp; easier to use.&lt;/p&gt;

&lt;p&gt;For instance, let's say that we are building a colour wheel, just like &lt;a href="https://www.canva.com/colors/color-wheel/" rel="noopener noreferrer"&gt;this one that I have found on canva.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to make our colour wheel work, we'll need to calculate what colours do we have in order to render them. Since we know that on the Web we use the RGB colour scheme, we are able to say that we have 256 * 256 * 256 colours available (which is about &lt;strong&gt;17 million&lt;/strong&gt; colours!), so it looks like our colour wheel is going to be &lt;em&gt;really&lt;/em&gt; huge.&lt;/p&gt;

&lt;p&gt;However, today, the design is not our primary concern. The main question now is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do we calculate all possible combinations of three numbers in the range from 0 to 255?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thanks to &lt;a href="https://math.stackexchange.com/a/3436451" rel="noopener noreferrer"&gt;this brilliant answer on math.stackexchange.com&lt;/a&gt; we now know that it's relatively easy to calculate all possible combinations using nested &lt;code&gt;for&lt;/code&gt; loops.&lt;/p&gt;

&lt;p&gt;Let's do a quick test to make sure it really works. We are going to calculate all combinations that can give us 2 numbers in the 0 - 1 range.&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="nx"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&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="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// -&amp;gt; [[ 0, 0 ], [ 0, 1 ], [ 1, 0 ], [ 1, 1 ]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works! So, in our case, luckily, we'll need just 3 nested loops.&lt;/p&gt;

&lt;p&gt;However, what if we would like to have a more generic function that could calculate all possible combinations for any set of numbers?&lt;/p&gt;

&lt;p&gt;Well, one option would be to create &lt;code&gt;for&lt;/code&gt; loops recursively.&lt;br&gt;
Let's create such a function &amp;amp; see it in action!&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/elegant-sound-pzvtl"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;If you inspect the screen above, you'll find out that it's made up of 10x10 &lt;code&gt;div&lt;/code&gt;s and each &lt;code&gt;div&lt;/code&gt; on the screen has a unique colour.&lt;/p&gt;

&lt;p&gt;Those colours are calculated automatically by &lt;code&gt;findAllNumericCombinations&lt;/code&gt; that generates exactly the needed number of nested loops to calculate all possible combinations of a given set of ranges.&lt;/p&gt;

&lt;p&gt;As you can see, only a few (particularly, 2304) colours are printed out. That's because printing out all 17 million would probably make your browser strongly dislike particular shades of orange :)&lt;/p&gt;

&lt;h2&gt;
  
  
  Iteration + Recursion = ❤️
&lt;/h2&gt;

&lt;p&gt;Now when you feel more comfortable with recursion, it's time to clarify that you don't necessarily need to stick to one or another.&lt;/p&gt;

&lt;p&gt;Iteration &amp;amp; recursion are not contradicting programming paradigms, not red &amp;amp; blue Matrix pills. Their light swords are of different colours but both are true Jedis!&lt;/p&gt;

&lt;p&gt;Jokes apart, sometimes it's quite convenient to mix both in order to get the desired result.&lt;/p&gt;

&lt;p&gt;You might already notice in previous examples that recursion &amp;amp; iteration might work quite well together.&lt;br&gt;
Let's see yet another example of such a synergy. Let's say we have an array that has a very misfortune structure and looks like this:&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;nestedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&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;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
  &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]]],&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]]]],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bad news is that it can only come in this form from the server, so, we must deal with it.&lt;/p&gt;

&lt;p&gt;The good news is that it always strictly follows the following rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Any array contains either other array(/s) or number(/s).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's say we want to increment each number in this array by 1 leaving the structure in exactly the same state as it came from the server.&lt;/p&gt;

&lt;p&gt;We'll have to use recursion since arrays that contain numbers might be nested at an arbitrary depth, so, we don't know beforehand how many iterations it will take to get to them.&lt;/p&gt;

&lt;p&gt;However, once we found an array that contains several numbers, how do we make our recursive function go through each number in the array?&lt;br&gt;
While we could implement this logic using recursion, it's not that fun to keep track of pointers position inside arrays.&lt;/p&gt;

&lt;p&gt;Shall we re-invent the wheel at all? Recursion is great at processing repetitive data structures while iteration is great at looping through arrays. So, there's no good reason to limit our toolbox to just one thing or another.&lt;/p&gt;

&lt;p&gt;Let's try to get the best out of the two worlds:&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="c1"&gt;// Fetched from server&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nestedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&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;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]],&lt;/span&gt;
  &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]]],&lt;/span&gt; &lt;span class="p"&gt;[[[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]]]],&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&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;incrementNestedNumbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// if array&lt;/span&gt;
      &lt;span class="nf"&gt;incrementNestedNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// if number&lt;/span&gt;
      &lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arrayWithNums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;incrementNestedNumbers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nestedNumbers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="cm"&gt;/* nestedNumbers now look like this:
  [[1], [[[[[[[2, 3]]]]]]], [4]],
  [[[5], [[6]]], [[[7, 8, 9]]]],
  [10]
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wonderful, isn't it? We use recursion to find all nested arrays &amp;amp; iteration to actually loop through them while both of our tools seem to enjoy working shoulder to shoulder.&lt;/p&gt;

&lt;p&gt;Some people will surely argue that this type of code can easily cause memory leaks &amp;amp; performance problems, however, from the practical point of view, if you understand what you are doing &amp;amp; test it well before using it in production, it will unlikely produce any undesired effects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Recursion is not &lt;strong&gt;that&lt;/strong&gt; difficult to understand.&lt;/li&gt;
&lt;li&gt;Recursion can be very useful for certain tasks, sometimes, it is the only way to achieve the desired result.&lt;/li&gt;
&lt;li&gt;Recursion might give you the power to abstract things that could not be abstracted without it.&lt;/li&gt;
&lt;li&gt;Recursion has its cons, most famous being that it can lead to an infinite loop or memory leaks too easily in some cases.&lt;/li&gt;
&lt;li&gt;There's no good reason why one should avoid learning about recursion or using it when it fits.&lt;/li&gt;
&lt;li&gt;Recursion is unlikely a tool that you will use every single day, however, it is a very valuable tool because it helps you think about programming problems in a broader &amp;amp; more structured way.&lt;/li&gt;
&lt;li&gt;Recursion pops-up in tech interviews quite frequently.&lt;/li&gt;
&lt;li&gt;Recursion &amp;amp; iteration might work well together, don't limit your toolbox by forcing yourself to choose just 1 of 2 available tools.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this article helped you to understand recursion a little better &amp;amp; you enjoyed it!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>tooling</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>React: Calling functional components as functions</title>
      <dc:creator>Igor Bykov</dc:creator>
      <pubDate>Wed, 26 Aug 2020 23:58:12 +0000</pubDate>
      <link>https://dev.to/igor_bykov/react-calling-functional-components-as-functions-1d3l</link>
      <guid>https://dev.to/igor_bykov/react-calling-functional-components-as-functions-1d3l</guid>
      <description>&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;To be a component ≠ Return JSX&lt;br&gt;
&lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; ≠ &lt;code&gt;Component()&lt;/code&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article tries to explain a somewhat advanced concept.&lt;/p&gt;

&lt;p&gt;One of my favourite things in web development is that almost any question can lead to an unforgettable deep dive that will reveal something completely new about a very familiar thing.&lt;/p&gt;

&lt;p&gt;That just happened to me, so now I know a tiny bit more about React &amp;amp; want to share it with you.&lt;/p&gt;

&lt;p&gt;It all started with a bug which we are going to reproduce now step by step. Here is the starting point:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/b0rl9?module=/src/App.js"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This app contains just 2 components &lt;code&gt;App&lt;/code&gt; &amp;amp; &lt;code&gt;Counter&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's inspect &lt;code&gt;App&lt;/code&gt;'s code:&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;const&lt;/span&gt; &lt;span class="nx"&gt;App&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTotal&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&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;incrementTotal&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;setTotal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentTotal&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentTotal&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"App"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Total Clicks: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h4&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"CountersContainer"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementTotal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementTotal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;incrementTotal&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Nothing interesting as for now, right? It just renders 3 &lt;code&gt;Counter&lt;/code&gt;s &amp;amp; keeps track and displays the sum of all counters.&lt;/p&gt;

&lt;p&gt;Now let's add a brief description to our app:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="p"&gt;const App = () =&amp;gt; {
&lt;/span&gt;  const [total, setTotal] = useState(0);
  const incrementTotal = () =&amp;gt; setTotal((currentTotal) =&amp;gt; currentTotal + 1);
&lt;span class="gi"&gt;+ const Description = () =&amp;gt; (
+   &amp;lt;p&amp;gt;
+     I like coding counters!
+     Sum of all counters is now {total}
+   &amp;lt;/p&amp;gt;
+ );
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h4&amp;gt;Total Clicks: {total}&amp;lt;/h4&amp;gt;
&lt;span class="gi"&gt;+       &amp;lt;Description /&amp;gt;
&lt;/span&gt;      &amp;lt;/div&amp;gt;
      &amp;lt;div className="CountersContainer"&amp;gt;
        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Works perfectly as before, but now it has a shiny new description, cool!&lt;/p&gt;

&lt;p&gt;You might notice that I declared component &lt;code&gt;Description&lt;/code&gt; instead of just writing JSX straight inside &lt;code&gt;App&lt;/code&gt;'s return statement.&lt;br&gt;
There might be plenty of reasons for that, let's just say that I wanted to keep JSX inside &lt;code&gt;App&lt;/code&gt;'s return clean &amp;amp; easily readable, so, I moved all messy JSX inside &lt;code&gt;Description&lt;/code&gt; component.&lt;/p&gt;

&lt;p&gt;You could also notice that I declared &lt;code&gt;Description&lt;/code&gt; &lt;strong&gt;inside&lt;/strong&gt; &lt;code&gt;App&lt;/code&gt;. It's not a standard way, but &lt;code&gt;Description&lt;/code&gt; needs to know the current state to display total clicks.&lt;br&gt;
I could refactor it and pass &lt;code&gt;total&lt;/code&gt; as a prop, but I don't plan to ever reuse &lt;code&gt;Description&lt;/code&gt; because I need just one for the whole app!&lt;/p&gt;

&lt;p&gt;Now, what if we also wanted to display some additional text above the central counter? Let's try to add it:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="p"&gt;const App = () =&amp;gt; {
&lt;/span&gt;  const [total, setTotal] = useState(0);
  const incrementTotal = () =&amp;gt; setTotal((currentTotal) =&amp;gt; currentTotal + 1);
  const Description = () =&amp;gt; (
    &amp;lt;p&amp;gt;
      I like coding counters!
      Sum of all counters is now {total}
    &amp;lt;/p&amp;gt;
  );
&lt;span class="gi"&gt;+
+ const CounterWithWeekday = (props) =&amp;gt; {
+   let today;
+   switch (new Date().getDay()) {
+     case 0:
+     case 6:
+       today = "a weekend!";
+       break;
+     case 1:
+       today = "Monday";
+       break;
+     case 2:
+       today = "Tuesday";
+       break;
+     default:
+       today = "some day close to a weekend!";
+       break;
+   }
+
+   return (
+     &amp;lt;div&amp;gt;
+       &amp;lt;Counter {...props} /&amp;gt;
+       &amp;lt;br /&amp;gt;
+       &amp;lt;span&amp;gt;Today is {today}&amp;lt;/span&amp;gt;
+     &amp;lt;/div&amp;gt;
+   );
+ };
&lt;/span&gt;&lt;span class="err"&gt;
&lt;/span&gt;  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h4&amp;gt;Total Clicks: {total}&amp;lt;/h4&amp;gt;
        &amp;lt;Description /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="CountersContainer"&amp;gt;
        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
&lt;span class="gd"&gt;-       &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+       &amp;lt;CounterWithWeekday onClick={incrementTotal} /&amp;gt;
&lt;/span&gt;        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};
&lt;span class="err"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Brilliant! Now we do have a bug! Check it out:&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/450vl?module=/src/App.js"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Note how &lt;code&gt;total&lt;/code&gt; is incremented when you click on the central counter, but the counter itself always stays at 0.&lt;/p&gt;

&lt;p&gt;Now, what surprised me is not the bug itself, but rather that I accidentally found out that the following works seamlessly:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;  return (
    &amp;lt;div className="App"&amp;gt;
      &amp;lt;div&amp;gt;
        &amp;lt;h4&amp;gt;Total Clicks: {total}&amp;lt;/h4&amp;gt;
        &amp;lt;Description /&amp;gt;
      &amp;lt;/div&amp;gt;
      &amp;lt;div className="CountersContainer"&amp;gt;
        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
&lt;span class="gd"&gt;-       &amp;lt;CounterWithWeekday onClick={incrementTotal} /&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+       { CounterWithWeekday({ onClick: incrementTotal }) }
&lt;/span&gt;        &amp;lt;Counter onClick={incrementTotal} /&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
  );
&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Surprised as well? Let's dive into together!&lt;/p&gt;

&lt;h2&gt;
  
  
  The bug
&lt;/h2&gt;

&lt;p&gt;The bug happens because we create brand new &lt;code&gt;CounterWithWeekday&lt;/code&gt; on each &lt;code&gt;App&lt;/code&gt; update.&lt;br&gt;
This happens because &lt;code&gt;CounterWithWeekday&lt;/code&gt; is declared inside &lt;code&gt;App&lt;/code&gt; which &lt;a href="https://dev.to/borasvm/react-create-component-inside-a-component-456b"&gt;might be considered an anti-pattern&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this particular case, it's easy to solve. Just move &lt;code&gt;CounterWithWeekday&lt;/code&gt; declaration outside of the &lt;code&gt;App&lt;/code&gt;, and the bug is gone.&lt;/p&gt;

&lt;p&gt;You might wonder why we don't have the same problem with &lt;code&gt;Description&lt;/code&gt; if it is also declared inside the &lt;code&gt;App&lt;/code&gt;.&lt;br&gt;
We actually do! It's just not obvious because React re-mounts the component so fast, that we can't notice and since this component has no inner state, it's not getting lost as in case of &lt;code&gt;CounterWithWeekday&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But why directly calling &lt;code&gt;CounterWithWeekday&lt;/code&gt; resolves the bug as well? Is it documented somewhere that you can just call a functional component as a plain function? What is the difference between the 2 options? Shouldn't a function return exactly the same thing disregard of the way it's invoked? 🤔&lt;/p&gt;

&lt;p&gt;Let's go step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Direct invocation
&lt;/h2&gt;

&lt;p&gt;From React documentation we know that component is just a plain JS class or function that eventually returns JSX (most of the time).&lt;/p&gt;

&lt;p&gt;However, if functional components are just functions, why wouldn't we call them directly? Why do we use &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; syntax instead?&lt;/p&gt;

&lt;p&gt;It turns out to be that &lt;a href="https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f" rel="noopener noreferrer"&gt;direct invocation was quite a hot topic for discussion&lt;/a&gt; in earlier versions of React. In fact, the author of the post &lt;a href="https://medium.com/@knoopx/fyi-https-babeljs-io-docs-plugins-transform-react-inline-elements-3ba87132acf5" rel="noopener noreferrer"&gt;shares a link to a Babel plug-in&lt;/a&gt; that (instead of creating React elements) helps in calling your components directly.&lt;/p&gt;

&lt;p&gt;I haven't found a single mention about calling functional components directly in React docs, however, there is one technique where such a possibility is demonstrated - &lt;a href="https://reactjs.org/docs/render-props.html" rel="noopener noreferrer"&gt;render props&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After some experiments, I came to quite a curious conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Component at all?
&lt;/h2&gt;

&lt;p&gt;Returning JSX, accepting props or rendering something to the screen has nothing to do with being a component.&lt;/p&gt;

&lt;p&gt;The same function might act as a component &amp;amp; as plain function at the same time.&lt;/p&gt;

&lt;p&gt;Being a component has much more to do with having own lifecycle &amp;amp; state.&lt;/p&gt;

&lt;p&gt;Let's check how &lt;code&gt;&amp;lt;CounterWithWeekday onClick={incrementTotal} /&amp;gt;&lt;/code&gt; from the previous example looks like in React dev tools:&lt;br&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%2Fi%2Fq1ro63ps57evv75o8dyc.png" 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%2Fi%2Fq1ro63ps57evv75o8dyc.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, it's a component that renders another component (&lt;code&gt;Counter&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Now let's change it to &lt;code&gt;{ CounterWithWeekday({ onClick: incrementTotal }) }&lt;/code&gt; and check React devtools again:&lt;br&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%2Fi%2Fnuo274mhmtxe1cbvbmd0.png" 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%2Fi%2Fnuo274mhmtxe1cbvbmd0.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Exactly! There's no &lt;code&gt;CounterWithWeekday&lt;/code&gt; component. It simply doesn't exist.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Counter&lt;/code&gt; component and text returned from &lt;code&gt;CounterWithWeekday&lt;/code&gt; are now direct children of &lt;code&gt;App&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Also, the bug is gone now because since &lt;code&gt;CounterWithWeekday&lt;/code&gt; component doesn't exist, the central &lt;code&gt;Counter&lt;/code&gt; doesn't depend on its lifecycle anymore, hence, it works &lt;em&gt;exactly the same&lt;/em&gt; as its sibling &lt;code&gt;Counter&lt;/code&gt;s.&lt;/p&gt;

&lt;p&gt;Here are a couple of quick answers to the questions I've been struggling with. Hope it'll help someone.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why &lt;code&gt;CounterWithWeekday&lt;/code&gt; component is not displayed in React dev tools anymore?
&lt;/h4&gt;

&lt;p&gt;The reason is that it's &lt;strong&gt;not a component&lt;/strong&gt; anymore, it's just a function call.&lt;/p&gt;

&lt;p&gt;When you do something like this:&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;const&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;it's clear that the variable &lt;code&gt;text&lt;/code&gt; is not a component.&lt;br&gt;
If it would return JSX, it wouldn't be a component.&lt;br&gt;
If it would accept a single argument called &lt;code&gt;props&lt;/code&gt;, it wouldn't be a component either.&lt;/p&gt;

&lt;p&gt;A function that &lt;em&gt;could be&lt;/em&gt; used as a component is not necessarily will be used as a component. So, to be a component, it needs to be used as &lt;code&gt;&amp;lt;Text /&amp;gt;&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;Same with &lt;code&gt;CounterWithWeekday&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By the way, components can return plain strings.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Counter doesn't lose state now?
&lt;/h4&gt;

&lt;p&gt;To answer that, let's answer why &lt;code&gt;Counter&lt;/code&gt;'s state was reset first.&lt;/p&gt;

&lt;p&gt;Here is what happens step by step:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;CounterWithWeekday&lt;/code&gt; is declared inside the &lt;code&gt;App&lt;/code&gt; &amp;amp; is used as a component.&lt;/li&gt;
&lt;li&gt;It is initially rendered.&lt;/li&gt;
&lt;li&gt;With each &lt;code&gt;App&lt;/code&gt; update, a new &lt;code&gt;CounterWithWeekday&lt;/code&gt; is created.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;CounterWithWeekday&lt;/code&gt; is a brand new function on each &lt;code&gt;App&lt;/code&gt; update, hence, React can't figure out that it's the same component.&lt;/li&gt;
&lt;li&gt;React clears &lt;code&gt;CounterWithWeekday&lt;/code&gt;'s  previous output (including its children) and mounts new &lt;code&gt;CounterWithWeekday&lt;/code&gt;'s output on each &lt;code&gt;App&lt;/code&gt; update. So, unlike other components, &lt;code&gt;CounterWithWeekday&lt;/code&gt; is never updated, but always mounted from scratch.&lt;/li&gt;
&lt;li&gt;Since &lt;code&gt;Counter&lt;/code&gt; is re-created on each &lt;code&gt;App&lt;/code&gt; update, its state after each parent update will always be 0.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, when we call &lt;code&gt;CounterWithWeekday&lt;/code&gt; as a function, it is also re-declared on each &lt;code&gt;App&lt;/code&gt; update, however, it doesn't matter anymore. Let's check hello world example once again to see why:&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;const&lt;/span&gt; &lt;span class="nx"&gt;HelloWorld&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;text&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello, World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;In this case, it wouldn't make sense for React to expect the &lt;code&gt;text&lt;/code&gt; reference to be the same when &lt;code&gt;HelloWorld&lt;/code&gt; is updated, right?&lt;/p&gt;

&lt;p&gt;In fact, React &lt;em&gt;cannot&lt;/em&gt; even check what &lt;code&gt;text&lt;/code&gt; reference is. It doesn't know that &lt;code&gt;text&lt;/code&gt; exists at all. React literally wouldn't notice the difference if we would just inline &lt;code&gt;text&lt;/code&gt; like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="err"&gt;

&lt;/span&gt;&lt;span class="p"&gt;const HelloWorld = () =&amp;gt; {
&lt;/span&gt;&lt;span class="gd"&gt;- const text = () =&amp;gt; 'Hello, World';
-
&lt;/span&gt;  return (
&lt;span class="gd"&gt;-   &amp;lt;h2&amp;gt;{text()}&amp;lt;/h2&amp;gt;
&lt;/span&gt;&lt;span class="gi"&gt;+   &amp;lt;h2&amp;gt;Hello, World&amp;lt;/h2&amp;gt;
&lt;/span&gt;  );
}
&lt;span class="err"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;So, by using &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; we make the component visible to React. However, since &lt;code&gt;text&lt;/code&gt; in our example is just called directly, React will never know about its existence.&lt;br&gt;
In this case, React just compares JSX (or text in this case). Until the content returned by &lt;code&gt;text&lt;/code&gt; is the same, nothing gets re-rendered.&lt;/p&gt;

&lt;p&gt;That exactly what happened to &lt;code&gt;CounterWithWeekday&lt;/code&gt;. If we don't use it like &lt;code&gt;&amp;lt;CounterWithWeekday /&amp;gt;&lt;/code&gt;, it is never exposed to React.&lt;/p&gt;

&lt;p&gt;This way, React will just compare &lt;strong&gt;the output&lt;/strong&gt; of the function, but not the function itself (as it would, in the case if we use it as a component).&lt;br&gt;
Since &lt;code&gt;CounterWithWeekday&lt;/code&gt;'s output is ok nothing gets re-mounted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A function that returns JSX might &lt;strong&gt;not&lt;/strong&gt; be a component, depending on how it is used.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To be a component function returning JSX should be used as &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; and not as &lt;code&gt;Component()&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a functional component is used as &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; it will have a lifecycle and can have a state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When a function is called directly as &lt;code&gt;Component()&lt;/code&gt; it will just run and (probably) return something. No lifecycle, no hooks, none of the React magic. It's very similar to assigning some JSX to a variable, but with more flexibility (you can use if statements, switch, throw, etc.). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://kentcdodds.com/blog/dont-call-a-react-function-component/" rel="noopener noreferrer"&gt;Using state in a non-component is dangerous&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Using functions that return JSX without being a component &lt;a href="https://github.com/yannickcr/eslint-plugin-react/issues/578" rel="noopener noreferrer"&gt;might be officially considered to be an anti-pattern in the future&lt;/a&gt;. There are edge cases (like render props), but generally, you almost always want to refactor those functions to be components because it's the recommended way.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If you have to declare a function that returns JSX inside a functional component (for instance, due to tightly coupled logic), directly calling it as &lt;code&gt;{component()}&lt;/code&gt; could be a better choice than using it as &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converting simple &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; into &lt;code&gt;{Component()}&lt;/code&gt; might be very handy for debugging purposes.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Handle loading errors &amp; fallback with HtmlWebpackPlugin</title>
      <dc:creator>Igor Bykov</dc:creator>
      <pubDate>Sun, 23 Aug 2020 20:44:53 +0000</pubDate>
      <link>https://dev.to/igor_bykov/handle-loading-errors-fallback-with-htmlwebpackplugin-2d31</link>
      <guid>https://dev.to/igor_bykov/handle-loading-errors-fallback-with-htmlwebpackplugin-2d31</guid>
      <description>&lt;p&gt;TL;DR&lt;/p&gt;

&lt;p&gt;If you use HtmlWebpackPlugin &amp;amp; sometimes things go wrong while your bundles are loading, &lt;a href="https://github.com/Uzwername/handling-script-loading-errors-HtmlWebpackPlugin"&gt;we’ve got you covered&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;Errors happen.&lt;/p&gt;

&lt;p&gt;This is particularly true about programming. However, when errors happen &lt;strong&gt;before&lt;/strong&gt; the code of your program even had a chance to execute, this is somewhat surprising &amp;amp; might be extremely tricky to handle.&lt;/p&gt;

&lt;p&gt;This is exactly the problem I had to deal with recently, and it seems likely that this might be a very common issue in client-side web apps.&lt;/p&gt;

&lt;p&gt;The error I have seen looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Uncaught SyntaxError: Unexpected token '&amp;lt;'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After some research, it turned out that the scenario when the error happened was something like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A user’s browser caches the page on the initial visit to the website. User doesn’t visit the site again until the &lt;em&gt;day X&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;We actively develop the website &amp;amp; make releases meanwhile&lt;/li&gt;
&lt;li&gt;Each new release adds a bundle with a unique hash to the server&lt;/li&gt;
&lt;li&gt;We store several latest releases on the server, however, since server resources are limited, with each new release coming in, we erase the oldest release&lt;/li&gt;
&lt;li&gt;It is &lt;em&gt;day X&lt;/em&gt; and the user with the cached version of the page happily comes in&lt;/li&gt;
&lt;li&gt;User’s browser tries to fetch &lt;code&gt;bundle.[too-old-hash].js&lt;/code&gt; but it doesn’t exist on the server since we already made several deploys and this old release was erased&lt;/li&gt;
&lt;li&gt;The server subsequently responds with 404 which is an HTML page&lt;/li&gt;
&lt;li&gt;JS compiler cannot parse HTML &amp;amp; throws &lt;code&gt;SyntaxError&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Our application would normally be rendered with React on client-side but since there is no bundle, the user sees a blank page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So, how do you handle an error that happens due to the fact that your entire application is unavailable? Below I will show a possible frontend-only solution.&lt;/p&gt;

&lt;p&gt;If you prefer to code along, you can find &lt;a href="https://github.com/Uzwername/handling-script-loading-errors-HtmlWebpackPlugin/tree/initial-state"&gt;sample repo with all setup but no solution implemented here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;

&lt;p&gt;We use &lt;a href="https://webpack.js.org/"&gt;webpack&lt;/a&gt; to compile &amp;amp; bundle our code and &lt;a href="https://github.com/jantimon/html-webpack-plugin"&gt;HtmlWebpackPlugin&lt;/a&gt; to generate an HTML page where our application will eventually live.&lt;/p&gt;

&lt;p&gt;Our application could be whatever. This article is framework-agnostic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Possible solutions &amp;amp; caveats
&lt;/h2&gt;

&lt;p&gt;First of all, logically we will not be able to do anything in the &lt;code&gt;bundle.[hash].js&lt;/code&gt;, because this file will fail to load &amp;amp; will be unavailable during runtime.&lt;/p&gt;

&lt;p&gt;So, what do we do? Well, we could add some inline JS on our page. It will always be present &amp;amp; hence, will be able to do some handling.&lt;/p&gt;

&lt;p&gt;Let’s create &lt;code&gt;src/index.ejs&lt;/code&gt; which is the default place for the template used by HtmlWebpackPlugin to generate the HTML page. By creating this file, we will be able to customize the HTML skeleton of the generated page.&lt;/p&gt;

&lt;p&gt;My first naive attempt was to add some inline JS in HtmlWebpackPlugin template to listen for &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/error_event"&gt;error event&lt;/a&gt; on the app’s script tag like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/index.ejs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;"ltr"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Handling script loading errors with HtmlWebpackPlugin&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;showErrorPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Doesn't matter for now&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;appScript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[src^="bundle"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;appScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showErrorPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})();&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
    &lt;span class="c"&gt;&amp;lt;!--
    HTMLWebpackPlugin will insert bundled script here on build.
    It will look something like this:

    &amp;lt;script src="bundle.foo12.js"&amp;gt;&amp;lt;/script&amp;gt;
    --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, this will not work because when inline &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;’s code is executed, &lt;code&gt;&amp;lt;script src="bundle.foo12.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt; does not even exist yet in the DOM because it is located below the inline script tag and it hasn’t been parsed by the browser yet. Ok, let’s wait until the DOM is ready &amp;amp; once it is, let’s do the same and attach the event listener (below I will omit unchanged parts of the document for brevity):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/index.ejs&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;showErrorPage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Doesn't matter for now&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;appScript&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[src^="bundle"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;appScript&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showErrorPage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unfortunately, this will not work either because when the browser sees the plain script tag that tries to load our bundle, it fetches and executes the bundle straight away, then it resumes HTML parsing and once it reaches &lt;code&gt;&amp;lt;/html&amp;gt;&lt;/code&gt; it fires the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/DOMContentLoaded_event"&gt;&lt;code&gt;DOMContentLoaded&lt;/code&gt; event&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Here is what it looks like graphically:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ljp4GOIg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ydm38v71wyndapjx2tkz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ljp4GOIg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ydm38v71wyndapjx2tkz.png" alt="Alt Text" width="880" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, we attach event listener long ago fetching and execution stages are completed and our callback will never be fired.&lt;br&gt;
So, it looks like we come either too early or too late.&lt;/p&gt;

&lt;p&gt;At this stage, we could try to check the bundle’s script presence in the DOM with a very short interval or some other brute-force solution of this type.&lt;/p&gt;

&lt;p&gt;Luckily, this is not necessary since HtmlWebpackPlugin provides us with everything to implement an elegant &amp;amp; efficient solution.&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;We clearly need to listen for loading events.&lt;br&gt;
However, in order to be able to listen for loading events, we need more control over &lt;strong&gt;when&lt;/strong&gt; our bundle starts to load to attach event listeners on time.&lt;/p&gt;

&lt;p&gt;Ok, let’s overtake control.&lt;/p&gt;

&lt;p&gt;First of all, let’s tell HtmlWebpackPlugin that we don’t want it to inject &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;‘s that we can't control into the page.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;webpack.config.js&lt;/code&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="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HtmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we don’t have bundle’s &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag at all, so, our app will never be loaded. That’s no good, but we can create &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag ourselves using the information HtmlWebpackPlugin provides to us.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;src/index.ejs&lt;/code&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oops, something went wrong! Please reload the page.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Paths of all bundles&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;htmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Create script tag &amp;amp; configure it&lt;/span&gt;
        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scriptTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Append script tag into body &lt;/span&gt;
        &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you use a template &lt;a href="https://github.com/jantimon/html-webpack-plugin#writing-your-own-templates"&gt;HtmlWebpackPlugin will pass a variable called &lt;code&gt;htmlWebpackPlugin&lt;/code&gt; to it&lt;/a&gt;. Here we access &lt;code&gt;htmlWebpackPlugin.files.js&lt;/code&gt; which is an array that contains paths of all javascript bundles created by webpack during this run.&lt;/p&gt;

&lt;p&gt;This strange construction “&lt;code&gt;&amp;lt;%= … %&amp;gt;&lt;/code&gt;” is just &lt;a href="https://ejs.co/"&gt;Embedded JavaScript templating&lt;/a&gt; syntax for printing information into the document.&lt;br&gt;
In this case, it will be resolved on the build to something like &lt;code&gt;['bundle.foo12.js']&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once we get the array of paths, we can iterate through this array and create a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag for each path.&lt;br&gt;
Before inserting the newly created &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; into the document, we will attach our error listener to it. This time we attached the listener on time, so, if any error happens, it will be fired.&lt;/p&gt;

&lt;p&gt;Note that I’m trying to use ES5-compliant syntax here because this code will not be compiled &amp;amp; will be shipped into the browser as it is.&lt;/p&gt;
&lt;h2&gt;
  
  
  Bonus: Insert images in the error message
&lt;/h2&gt;

&lt;p&gt;IRL we probably want to show some nice “error page” instead of a message in browser’s alert box. Probably, we want to show an image on the error page.&lt;/p&gt;

&lt;p&gt;There is no problem with it. Our template is flexible enough to make it possible.&lt;/p&gt;

&lt;p&gt;First of all, let’s install &lt;a href="https://webpack.js.org/loaders/file-loader/"&gt;file-loader&lt;/a&gt; that can handle images.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;terminal&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;file-loader &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let’s tell webpack to use this loader.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;webpack.config.js&lt;/code&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\.(&lt;/span&gt;&lt;span class="sr"&gt;png|jpe&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;g|gif&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;$/i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;file-loader&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can directly require images inside our &lt;code&gt;index.ejs&lt;/code&gt; template like this:&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="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./path_to_image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the full &lt;code&gt;src/index.ejs&lt;/code&gt; file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;dir=&lt;/span&gt;&lt;span class="s"&gt;"ltr"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Handling script loading errors with HtmlWebpackPlugin&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;style&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;#bundleLoadingErrorContainer&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;position&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;fixed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;flex-direction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;column&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#FFF&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nc"&gt;.bundle_error_title&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nl"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;1.5%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;h1&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"bundleLoadingErrorContainer"&lt;/span&gt; &lt;span class="na"&gt;style=&lt;/span&gt;&lt;span class="s"&gt;"display: none;"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;h2&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"bundle_error_title"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Oops, something went wrong. Please reload the page.&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;figure&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"photo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"&amp;lt;%= require('./assets/bird.jpg').default %&amp;gt;"&lt;/span&gt; &lt;span class="na"&gt;width=&lt;/span&gt;&lt;span class="s"&gt;"300"&lt;/span&gt; &lt;span class="na"&gt;height=&lt;/span&gt;&lt;span class="s"&gt;"200"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"bird"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;br&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;figcaption&amp;gt;&lt;/span&gt;
                Photo by &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unsplash.com/@photoholgic"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"external noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Holger Link&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt; on &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://unsplash.com/"&lt;/span&gt; &lt;span class="na"&gt;target=&lt;/span&gt;&lt;span class="s"&gt;"_blank"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"external noopener"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Unsplash&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/figcaption&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/figure&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bundleLoadingErrorContainer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;removeAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;style&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;%=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;htmlWebpackPlugin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;files&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;scriptTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bundlesSrcs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;showErrorMessage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;scriptTag&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;})();&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hope it was helpful! You can find all the code of the final version in &lt;a href="https://github.com/Uzwername/handling-script-loading-errors-HtmlWebpackPlugin"&gt;this repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, we’re all done and you can test how error handler works using not so well-known &lt;a href="https://developers.google.com/web/updates/2017/04/devtools-release-notes#block-requests"&gt;Chrome’s request blocking feature&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webpack</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
