<?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: Ramo Mujagic</title>
    <description>The latest articles on DEV Community by Ramo Mujagic (@rmmgc).</description>
    <link>https://dev.to/rmmgc</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%2F967120%2F00a88138-68f9-48f7-98e1-e199f24fd512.jpeg</url>
      <title>DEV Community: Ramo Mujagic</title>
      <link>https://dev.to/rmmgc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rmmgc"/>
    <language>en</language>
    <item>
      <title>How to setup Deep Links for Android applications</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Sun, 09 Jun 2024 12:24:12 +0000</pubDate>
      <link>https://dev.to/rmmgc/how-to-setup-deep-links-for-android-applications-509e</link>
      <guid>https://dev.to/rmmgc/how-to-setup-deep-links-for-android-applications-509e</guid>
      <description>&lt;p&gt;Deep links are special URIs that take users directly to specific content within a mobile app, rather than just launching the app or opening a webpage in a browser.&lt;/p&gt;

&lt;p&gt;These links enhance user experience by letting users navigate to precise content or a particular section of the app with just one click.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types of links
&lt;/h2&gt;

&lt;p&gt;On Android, there are clear distinctions between different types of links: Deep Links, Web Links, and Android App Links. To implement deep link handling on Android, it's essential to understand how each type behaves. The following illustration shows the relationships between these types of links.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv4mcazuj1tbohejmkdv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkv4mcazuj1tbohejmkdv.png" alt="Relation between different links" width="260" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image, you can see that Web Links and Android App Links are special cases of deep links. Let's explore them a bit further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deep Links
&lt;/h3&gt;

&lt;p&gt;Deep links can take various forms depending on the URI scheme and the type of content they point to within the app. Here is an overview of possible schemes available with deep links:&lt;/p&gt;

&lt;p&gt;1️⃣ &lt;strong&gt;HTTP/HTTPS Scheme&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are URLs that can open web pages in a browser or specific content within the app if the app is set up to handle them. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://shopapp.com/shop
https://shopapp.com/profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;2️⃣ &lt;strong&gt;Custom Scheme&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;These are &lt;strong&gt;custom URI schemes&lt;/strong&gt; defined by the app. They don't open in a web browser and are designed to be &lt;strong&gt;handled only&lt;/strong&gt; by the app. Here is an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shopapp://shop
shopapp://profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that URI starts with &lt;code&gt;shopap&lt;/code&gt;, this is called &lt;strong&gt;custom scheme&lt;/strong&gt;. If there is an app on your Android device configured to handle this custom scheme, Android will delegate handling of the link to the capable app.&lt;/p&gt;

&lt;p&gt;In simple terms, deep links are URIs that navigate users directly to specific content within a mobile app and can use both HTTP/HTTPS and custom URI schemes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Links
&lt;/h3&gt;

&lt;p&gt;Web links are deep links that use the &lt;strong&gt;HTTP/HTTPS schemes&lt;/strong&gt;. Starting with Android 12, clicking a Web Link that is not an &lt;em&gt;Android App Link&lt;/em&gt; &lt;strong&gt;always shows&lt;/strong&gt; content in a web browser.&lt;/p&gt;

&lt;p&gt;On devices running previous versions of Android, if the app or other apps installed on a user's device can also handle the Web Link, users might not go directly to the browser. Instead, they'll see a system dialog letting them choose which app to use to open the link.&lt;/p&gt;

&lt;h3&gt;
  
  
  Android App Links
&lt;/h3&gt;

&lt;p&gt;Android App Links are a special type of URL designed for Android that looks similar to a regular web link (using HTTP/HTTPS). They allow users to be directed to specific content within an app, instead of a web page. Here are some examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://www.shopapp.com/product/67890
https://www.shopapp.com/profile/12345
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user clicks on an Android App Link, the app opens immediately if it's installed. The Android system will not show any modals to the user; it just works. If the user doesn't want your app to be the default handler, they can override this behavior in the app's settings.&lt;/p&gt;

&lt;p&gt;App Links are required to support deep linking behavior using HTTP/HTTPS scheme on Android 12 and onwards, ensuring a seamless user experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implicit Intent
&lt;/h2&gt;

&lt;p&gt;Before configuring deep links, it's important to understand how the Android system handles such links. This is done using something called an &lt;em&gt;Intent&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;In the world of Android apps, intents act as messengers. These messages coordinate actions between different parts of an app, or even between different apps entirely. There are two main types of intents: explicit intents and implicit intents. Today, we'll focus on implicit intents because they play a key role in deep linking and how the Android system directs users to specific app content.&lt;/p&gt;

&lt;p&gt;Implicit intents specify a &lt;strong&gt;general action to be performed&lt;/strong&gt;. They &lt;strong&gt;do not specify&lt;/strong&gt; which application to use for performing the action. The system decides which installed application is best suited to handle the implicit intent. To achieve this, the system checks something called &lt;strong&gt;intent filters&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Deep Links use Implicit Intents
&lt;/h3&gt;

&lt;p&gt;Deep links rely on &lt;strong&gt;intent filters&lt;/strong&gt; specified in the app's &lt;code&gt;AndroidManifest.xml&lt;/code&gt; to handle particular URL schemes or host/path combinations.&lt;/p&gt;

&lt;p&gt;When a deep link is triggered (e.g., a user clicks a link), an &lt;strong&gt;implicit intent is created&lt;/strong&gt; with the action &lt;code&gt;Intent.ACTION_VIEW&lt;/code&gt; and a data URI specifying the URL to be handled.&lt;/p&gt;

&lt;p&gt;Next, the Android system matches this intent against the intent filters declared by installed applications to find the appropriate activity to handle the link.&lt;/p&gt;

&lt;p&gt;When setting up deep links, our goal is to ensure that the system has all the necessary data required to start our application when the designated deep link gets triggered.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding intent filters
&lt;/h3&gt;

&lt;p&gt;When you define an intent filter in your &lt;code&gt;AndroidManifest.xml&lt;/code&gt; to handle deep links, the system uses the specified &lt;code&gt;&amp;lt;data&amp;gt;&lt;/code&gt; attributes to match incoming intents to the correct activity. The &lt;code&gt;&amp;lt;data&amp;gt;&lt;/code&gt; element can specify the &lt;em&gt;scheme&lt;/em&gt;, &lt;em&gt;host&lt;/em&gt;, &lt;em&gt;port&lt;/em&gt;, &lt;em&gt;path&lt;/em&gt;, &lt;em&gt;pathPrefix&lt;/em&gt;, and &lt;em&gt;pathPattern&lt;/em&gt;. If these attributes do not match the incoming URL, the intent filter will not match, and the activity will not be triggered (e.g., the application will not start).&lt;/p&gt;

&lt;p&gt;Intent filters are crucial in handling deep links, allowing you to fine-tune how your application responds to specific links. We will discuss this in more detail in the next sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Link flow
&lt;/h2&gt;

&lt;p&gt;Deep links can seem complex at first, but the following flowchart will break it down into simpler steps. Let's see how deep links navigate users to specific app content.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzd4urgmqkel20wbnkxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzd4urgmqkel20wbnkxj.png" alt="Flowchart that shows how the Android handles deep links" width="800" height="1298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The flowchart illustrates how the Android system resolves deep links, which can be in the form of a custom domain or an App Link.&lt;/p&gt;

&lt;p&gt;The process begins with the user triggering the deep link. This can happen by pressing a button or clicking a link, for example in an email or messaging app. Upon this action, the Android system creates an implicit intent using the URL associated with the button or link.&lt;/p&gt;

&lt;p&gt;The system checks the intent filters declared in &lt;code&gt;AndroidManifest.xml&lt;/code&gt; for every installed app to find a matching filter that can handle the URL.&lt;/p&gt;

&lt;p&gt;The system then checks if any installed apps have registered an intent filter that can handle the URL from the deep link and analyzes the deep link further to determine its specific type.&lt;/p&gt;

&lt;p&gt;If the deep link uses a custom URI scheme but no matching app is found, the link isn't handled by the Android system. In all other cases, the link opens in a web browser.&lt;/p&gt;

&lt;p&gt;If the system finds a matching intent filter, it takes further action based on the deep link type. For custom URI schemes, the link is directly opened within the corresponding app. However, for App Links, an additional step verifies domain ownership to ensure security. We'll explore this verification process in detail later. For now, let's focus on what happens after successful verification of an App Link.&lt;/p&gt;

&lt;p&gt;Upon successful domain ownership verification, the link opens directly within the app. However, if verification fails, the link will be opened in a web browser for user safety.&lt;/p&gt;

&lt;p&gt;I hope this gives you a clearer picture of how deep links are processed and handled by the system. If it's still not clear, consider reading this section once more.&lt;/p&gt;

&lt;p&gt;Now, let's dive deeper and explore how to configure App Links to leverage this functionality within your own app!&lt;/p&gt;

&lt;h2&gt;
  
  
  Using App Links
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, App Links are a special type of URL designed for Android that looks similar to a regular web link. Since App Links use the HTTP/HTTPS scheme, we need to configure them for designated web URLs.&lt;/p&gt;

&lt;p&gt;Setting up App Links involves a few key steps to ensure that your application can handle URLs and open the app directly when those URLs are clicked.&lt;/p&gt;

&lt;p&gt;Before we start, let's say we want to configure the app so that when the following link is clicked: &lt;code&gt;https://shopapp.com/shop&lt;/code&gt;, it opens the &lt;em&gt;ShopActivity&lt;/em&gt; inside the app itself.&lt;/p&gt;

&lt;p&gt;There are a couple of important pieces of information that we can extract from the link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host: &lt;code&gt;shopapp.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Scheme: &lt;code&gt;https&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Pathname: &lt;code&gt;/shop&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We will later use this information to construct the required intent filter needed to open the app when the link is triggered. So, let's get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update Manifest file
&lt;/h3&gt;

&lt;p&gt;First, we need to declare intent filters in the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; for the activity that should handle our link.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;".ShopActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;intent-filter&lt;/span&gt; &lt;span class="na"&gt;android:autoVerify=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span class="c"&gt;&amp;lt;!-- Define the scheme, host and path --&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt;
    &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"https"&lt;/span&gt;
    &lt;span class="na"&gt;android:host=&lt;/span&gt;&lt;span class="s"&gt;"shopapp.com"&lt;/span&gt;
    &lt;span class="na"&gt;android:pathPrefix=&lt;/span&gt;&lt;span class="s"&gt;"/shop"&lt;/span&gt;
    &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, what just happened? Let's break it down.&lt;/p&gt;

&lt;p&gt;One very important attribute is &lt;code&gt;android:autoVerify="true"&lt;/code&gt;, and links &lt;strong&gt;will not work&lt;/strong&gt; without it! According to Google, this attribute allows the app to designate itself as the default handler of a given type of link. So, when the user clicks on an Android App Link, your app opens immediately if it's installed.&lt;/p&gt;

&lt;p&gt;The intent filter that we just created will only match &lt;code&gt;https://shopapp.com/shop&lt;/code&gt;, but what if we want to open the app when &lt;code&gt;https://shopapp.com&lt;/code&gt; link is clicked? Well, we can modify the intent filter and remove the &lt;code&gt;android:pathPrefix="/shop"&lt;/code&gt; attribute, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;intent-filter&lt;/span&gt; &lt;span class="na"&gt;android:autoVerify=&lt;/span&gt;&lt;span class="s"&gt;"true"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

  &lt;span class="c"&gt;&amp;lt;!-- Define the scheme and host --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt;
    &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"https"&lt;/span&gt;
    &lt;span class="na"&gt;android:host=&lt;/span&gt;&lt;span class="s"&gt;"shopapp.com"&lt;/span&gt;
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will match any URL with the scheme &lt;strong&gt;https&lt;/strong&gt; and host &lt;code&gt;shopapp.com&lt;/code&gt;, regardless of the path. So, URLs like &lt;code&gt;https://shopapp.com&lt;/code&gt;, &lt;code&gt;https://shopapp.com/shop&lt;/code&gt;, and &lt;code&gt;https://shopapp.com/profile/1117&lt;/code&gt; would all open the application.&lt;/p&gt;

&lt;p&gt;You might wonder, when this is the case, why even use &lt;code&gt;android:pathPrefix&lt;/code&gt; attribute? There are a couple of reason to consider, but most important is &lt;em&gt;Selective Handling&lt;/em&gt;. This basically means that you can ensure that &lt;strong&gt;only specific paths&lt;/strong&gt; within your domain are handled by your application.&lt;/p&gt;

&lt;p&gt;If your website has different parts like &lt;code&gt;/shop&lt;/code&gt;, &lt;code&gt;/categories&lt;/code&gt; and &lt;code&gt;/profile&lt;/code&gt;, and you only want the app to handle links under &lt;code&gt;/shop&lt;/code&gt;, you would use &lt;code&gt;android:pathPrefix="/shop"&lt;/code&gt; to ensure that the app only opens links that have &lt;code&gt;/shop&lt;/code&gt; as a path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the Digital Asset Links File
&lt;/h3&gt;

&lt;p&gt;Great, now we have intent filter that say to the system: “Hey, when you see this link &lt;code&gt;https://shopapp.com/shop&lt;/code&gt; being clicked somewhere please open our app”.&lt;/p&gt;

&lt;p&gt;But, this is still not enough. The system will not trust our app without &lt;strong&gt;proof that we own the link domain&lt;/strong&gt;. Why, you might wonder?&lt;/p&gt;

&lt;p&gt;Well, we could have added an intent filter for &lt;code&gt;https://amazon.com/&lt;/code&gt;, but we obviously do not own this domain, and it would be really weird, and a major safety hazard, if the system would use our app to handle the link that points to the &lt;code&gt;amazon.com&lt;/code&gt; domain.&lt;/p&gt;

&lt;p&gt;So how can we prove to the system that we actually own the domain of the link? This is where the &lt;strong&gt;Digital Asset Links File&lt;/strong&gt; comes into play. This file is used to prove the ownership of the domain (e.g., the association between your website and your app).&lt;/p&gt;

&lt;p&gt;This file needs to be named &lt;code&gt;assetlinks.json&lt;/code&gt;, and as the file extension implies, it needs to be in JSON format. This is how the file might look:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"relation"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"delegate_permission/common.handle_all_urls"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"android_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"package_name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"com.shopapp.app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"sha256_cert_fingerprints"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="s2"&gt;"XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the file is an array, and the configuration for our application is contained in an object. This means if you own multiple apps that can open the links from your website, you need to list the configuration for both (or more) apps in this file.&lt;/p&gt;

&lt;p&gt;For Android apps, you will have to modify only the &lt;code&gt;package_name&lt;/code&gt; and &lt;code&gt;sha256_cert_fingerprints&lt;/code&gt; attributes. The &lt;code&gt;package_name&lt;/code&gt; is pretty self-explanatory; it is the package name of your app.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;sha256_cert_fingerprints&lt;/code&gt; attribute, you need to put the SHA-256 fingerprint of your app's signing certificate. There can be multiple fingerprints added (e.g., debug and production).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Warning&lt;br&gt;
When adding certificate, it is important to use capital letters for HEX values! Not using capital letters might prevent the system from opening your app (errorCode: ERROR_CODE_MALFORMED_CONTENT).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you do not know your SHA-256 fingerprint, you can use the following &lt;code&gt;keytool&lt;/code&gt; command to get it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;keytool &lt;span class="nt"&gt;-list&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-keystore&lt;/span&gt; &amp;lt;path-to-keystore&amp;gt; &lt;span class="nt"&gt;-alias&lt;/span&gt; &amp;lt;key-alias&amp;gt; &lt;span class="nt"&gt;-storepass&lt;/span&gt; &amp;lt;keystore-password&amp;gt; &lt;span class="nt"&gt;-keypass&lt;/span&gt; &amp;lt;key-password&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure to replace the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;path-to-keystore&amp;gt;&lt;/code&gt; - Path to the keystore file used to sign the app.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;key-alias&amp;gt;&lt;/code&gt; - Alias name given to the keystore when it was created.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;keystore-password&amp;gt;&lt;/code&gt; - Keystore password given to the keystore when it was created.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;&amp;lt;key-password&amp;gt;&lt;/code&gt; - Key password given when the keystore was created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is important to add the correct SHA-256 fingerprint to the &lt;code&gt;sha256_cert_fingerprints&lt;/code&gt; attribute or the link will not work!&lt;/p&gt;

&lt;p&gt;If you are debugging the app using the default Android keystore, you can get the fingerprint for it using the following command and add it to the &lt;code&gt;sha256_cert_fingerprints&lt;/code&gt; as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;keytool &lt;span class="nt"&gt;-list&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-keystore&lt;/span&gt; ~/.android/debug.keystore &lt;span class="nt"&gt;-alias&lt;/span&gt; androiddebugkey &lt;span class="nt"&gt;-storepass&lt;/span&gt; android &lt;span class="nt"&gt;-keypass&lt;/span&gt; android
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this done, your &lt;code&gt;assetlinks.json&lt;/code&gt; should be ready, and we can move to the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  Upload Digital Asset Links File to website host
&lt;/h3&gt;

&lt;p&gt;We've created the &lt;code&gt;assetlinks.json&lt;/code&gt; file, but it won't work its magic just sitting on your computer. Let's explore what the Android system needs from us to leverage this file for App Link verification.&lt;/p&gt;

&lt;p&gt;When the Android system tries to verify the &lt;code&gt;https://shopapp.com/shop&lt;/code&gt; link, it will make a GET request to a specific location on our website. In our example, the request URL will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;https://shopapp.com/.well-known/assetlinks.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;.well-known/assetlinks.json&lt;/code&gt; path in the link. The Android system will try to get our Digital Asset Links File from that location. This means we need to upload/host our previously created &lt;code&gt;assetlinks.json&lt;/code&gt; in that specific location.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Warning&lt;br&gt;
The &lt;code&gt;assetlinks.json&lt;/code&gt; file must be hosted in the &lt;code&gt;.well-known&lt;/code&gt; directory at the &lt;strong&gt;root of the domain&lt;/strong&gt; to work correctly.&lt;br&gt;
That means, URL like &lt;code&gt;https://shopapp.com/shop/.well-known/assetlinks.json&lt;/code&gt; will not work because &lt;code&gt;/shop&lt;/code&gt; path is added.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here's what the Android system expects for your &lt;code&gt;assetlinks.json&lt;/code&gt; file to function correctly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Directly Accessible: The file must be reachable without any redirects.&lt;/li&gt;
&lt;li&gt;Open to Bots: The file needs to be accessible by automated programs (bots).&lt;/li&gt;
&lt;li&gt;Correct Content Type: The file's content type should be identified as &lt;code&gt;application/json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Secure Connection: The file must be served over a secure HTTPS connection for added security.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In most cases, simply uploading your &lt;code&gt;assetlinks.json&lt;/code&gt; file as a static file to &lt;code&gt;https://&amp;lt;your_domain_name&amp;gt;/.well-known/assetlinks.json&lt;/code&gt; will be good enough to satisfy all the requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify that Digital Asset Links File is correct
&lt;/h3&gt;

&lt;p&gt;Let's assume we have our Digital Assets Link File hosted on &lt;code&gt;https://shopapp.com/shop/.well-known/assetlinks.json&lt;/code&gt; and ready to be used. How can we know that the configuration is correct and the Android system will be able to use it? Luckily, for this reason, Google provides a Digital Asset Links API to verify the accuracy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://&amp;lt;domain_name&amp;gt;&amp;amp;relation=delegate_permission/common.handle_all_urls
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can execute this request straight in you browser, make sure to replace &lt;code&gt;&amp;lt;domain_name&amp;gt;&lt;/code&gt; with the correct domain name of your website.&lt;/p&gt;

&lt;p&gt;If the API encounters any problems processing your assets file, it will return an error code along with additional details about the issue. This information can help you diagnose and fix problems within your asset file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test App Links on Device
&lt;/h3&gt;

&lt;p&gt;The best way to know if deep links are working is, obviously, to test them on the device. To test deep links, you can either use a real device or an Android emulator.&lt;/p&gt;

&lt;p&gt;Before any testing can happen, let's follow some setup phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make sure that &lt;code&gt;AndroidManifest.xml&lt;/code&gt; is properly configured.&lt;/li&gt;
&lt;li&gt;Use the correct signing certificate (keystore), the one you added to the &lt;code&gt;assetlinks.json&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Create new app build.&lt;/li&gt;
&lt;li&gt;Install the app on device or emulator.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With the setup out of the way, we can start testing deep links. The first thing we can do is to artificially create test deep links using the &lt;code&gt;adb&lt;/code&gt; command like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell am start &lt;span class="nt"&gt;-W&lt;/span&gt; &lt;span class="nt"&gt;-a&lt;/span&gt; android.intent.action.VIEW &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"https://shopapp.com/shop"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command simulates a deep link click on your connected device or emulator. It essentially tells the system to launch an activity capable of handling the provided URL, mimicking how the system would normally create an implicit intent for a deep link. Think of it as manually crafting an intent to test your app's deep link response. Remember to replace &lt;code&gt;https://shopapp.com/shop&lt;/code&gt; with your actual deep link.&lt;/p&gt;

&lt;p&gt;If our setup was correct, the System will open the link in our app rather than opening it in the browser.&lt;/p&gt;

&lt;p&gt;For a more hands-on test, you can leverage the deep link itself! Send yourself an email or message containing the link, or generate a QR code from the link and scan it using your device's camera app. If the app is installed on your device, clicking the link or scanning the QR code should automatically launch the app and navigate to the intended content.&lt;/p&gt;

&lt;p&gt;If you have some issues, make sure you followed the guide correctly and that nothing is skipped over.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Deep Links with Custom scheme
&lt;/h2&gt;

&lt;p&gt;Deep links with a custom scheme are another way to implement deep linking functionality. While deep links via the HTTP/HTTPS scheme are more commonly used, custom schemes can also come in handy in some cases.&lt;/p&gt;

&lt;p&gt;So how to set it up? Luckily, it can be done in just one step compare to App Links that involved quite a lot things to go trough.&lt;/p&gt;

&lt;h3&gt;
  
  
  Update manifest file
&lt;/h3&gt;

&lt;p&gt;As with App Links, we need to define an intent filter in the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file to specify the custom URI scheme that the app will handle.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;activity&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;".ShopActivity"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;intent-filter&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;action&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.action.VIEW"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.DEFAULT"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;category&lt;/span&gt; &lt;span class="na"&gt;android:name=&lt;/span&gt;&lt;span class="s"&gt;"android.intent.category.BROWSABLE"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;

        &lt;span class="c"&gt;&amp;lt;!-- Define custom scheme --&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;data&lt;/span&gt; &lt;span class="na"&gt;android:scheme=&lt;/span&gt;&lt;span class="s"&gt;"shopapp"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/intent-filter&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/activity&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The intent filter for a custom scheme deep link resembles the one for App Links, but with a key difference. The crucial attribute here is &lt;code&gt;android:scheme&lt;/code&gt;, which specifies the custom scheme your app will respond to. In this example, the &lt;code&gt;shopapp&lt;/code&gt; scheme is defined.&lt;/p&gt;

&lt;p&gt;It goes without saying, but we also need to add code to the Activity to handle the deep link intent. However, as this is not part of our topic, we will skip it.&lt;/p&gt;

&lt;p&gt;Believe it or not, with this setup, the configuration is actually completed. Our app should open when someone triggers a link like this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;shopapp://shop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Android system will create an intent, check intent filters, and open the app immediately without any validation or modals in between—it just works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Test link on Device
&lt;/h3&gt;

&lt;p&gt;To test your custom scheme, similar to App Links, we can use the &lt;code&gt;adb&lt;/code&gt; command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;adb shell am start &lt;span class="nt"&gt;-a&lt;/span&gt; android.intent.action.VIEW &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s2"&gt;"shopapp://shop"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command triggers an activity on the connected Android device or emulator to handle the specified URL, testing how the app responds to the deep link. If the app is installed and set up correctly, the link should open in the app.&lt;/p&gt;

&lt;p&gt;Another way to test it us by creating a simple HTML file with a link that uses our custom scheme.&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&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;title&amp;gt;&lt;/span&gt;Test Custom Scheme&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;a&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"shopapp://shop"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Open App&lt;span class="nt"&gt;&amp;lt;/a&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;You can use a simple static HTTP server to serve the file. Open the file on the device and click on the "Open App" button. When the link is triggered, the system should open the link in the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Deep links are a powerful tool in today's mobile development landscape. Integrating deep links into your app can significantly improve user interaction by allowing users to access specific features or content directly from external sources.&lt;/p&gt;

&lt;p&gt;We explored key deep link concepts and provided instructions for setting up deep links in Android applications. By understanding these concepts and implementing the discussed techniques, developers can leverage deep links to enhance user navigation, streamline user journeys, and ultimately create a more engaging app experience. Whether through custom URI schemes or verified web links (App Links), deep linking offers a robust solution for guiding users to specific content and improving the overall app experience.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://wannabedev.io/"&gt;wannabedev.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>android</category>
      <category>mobile</category>
      <category>learning</category>
      <category>deeplinks</category>
    </item>
    <item>
      <title>Visualize Bubble Sort Algorithm using SVG</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Mon, 09 Oct 2023 18:01:27 +0000</pubDate>
      <link>https://dev.to/rmmgc/visualize-bubble-sort-algorithm-using-svg-2n16</link>
      <guid>https://dev.to/rmmgc/visualize-bubble-sort-algorithm-using-svg-2n16</guid>
      <description>&lt;p&gt;I was playing around with some SVG (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/SVG"&gt;Scalable Vector Graphics&lt;/a&gt;) for some time and wanted to make a quick article about it. The problem was that I had no idea what to create using SVG. Fortunately, I stumbled upon one thread about sorting algorithms and thought it would be interesting to animate how sorting algorithms work.&lt;/p&gt;

&lt;p&gt;Of course, I decided to go with the simples of the bunch, Bubble Sort, just to give it a try. To cut to the chase, you can check it out on the &lt;a href="https://wannabedev.io/_posts/visualize-bubble-sort-algorithm-using-svg/demo/index.html"&gt;demo page&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Bubble Sort works
&lt;/h2&gt;

&lt;p&gt;Most of you already know about sorting algorithms, but let's just give a quick introduction to Bubble Sort so we understand how it works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you know how the Bubble Sort algorithm works, feel free to skip to the next section.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bubble Sort is a straightforward sorting algorithm that involves repeatedly comparing and swapping adjacent elements in a list until the list is sorted.&lt;/p&gt;

&lt;p&gt;Let's say we have following list of numbers:&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="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;6&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Bubble Sort algorithm will loop over this list a total of &lt;code&gt;n - 1&lt;/code&gt; times, where &lt;code&gt;n&lt;/code&gt; is the number of elements in the list. This means, for our example, Bubble Sort will loop over the list &lt;strong&gt;four times&lt;/strong&gt; in total.&lt;/p&gt;

&lt;p&gt;Let's see what happens in the &lt;strong&gt;first pass&lt;/strong&gt; through the list:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It begins by comparing the first and second elements, starting with the first index (numbers 5 and 6). No swap is needed.&lt;/li&gt;
&lt;li&gt;Next, compare 6 and 9. No swap is needed.&lt;/li&gt;
&lt;li&gt;Next, compare 9 and 2. Swap the numbers since they are not ordered.&lt;/li&gt;
&lt;li&gt;Continue this process until the biggest numbers ”bubble” up to the top.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end of the first pass, we will have the following list of numbers:&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="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;6&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;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the &lt;strong&gt;second pass&lt;/strong&gt;, exactly the same thing will happen, but in this case we do not have to compare with the last number in the list since we already know that it's the biggest number. At the end of the second pass, we will have the following list of numbers:&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="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;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;6&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are almost there; when the &lt;strong&gt;third pass&lt;/strong&gt; starts, we do not have to check for the last two numbers in the list since we know that the list does not have bigger numbers. At the end of the third pass, we will have the following list of numbers:&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="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;5&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;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmmm, it looks like the list is already sorted, and we did not even start the fourth pass. Well, that can happen, but it does not really matter.&lt;/p&gt;

&lt;p&gt;There is nothing to prevent the algorithm from starting the final, &lt;strong&gt;forth&lt;/strong&gt;, pass. At least it will be a quick one since we know that the last three numbers are already sorted. And as we expected, at the end of the fourth pass, the list stays the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prepare wireframe
&lt;/h2&gt;

&lt;p&gt;So, there is a simple question: how can we visualize the Bubble Sort algorithm? Let's start with the basics and define what we want to make. Take a look at the following image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MblJzQbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ww3um3fb3nuk1n8i2oyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MblJzQbd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ww3um3fb3nuk1n8i2oyb.png" alt="Wireframe of the animation player and controls" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image, you can see the basic UI of our Bubble Sort visualization player. We will have two inputs that allow us to tweak player settings a little bit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Number of items - changes the number of items in the list.&lt;/li&gt;
&lt;li&gt;Animation speed - changes the time it takes for animation to finish a single step.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Underneath, we have three buttons that control the player.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Play” button - starts the visualization.&lt;/li&gt;
&lt;li&gt;“Pause” button - pauses the currently running visualization.&lt;/li&gt;
&lt;li&gt;“Stop” button - stops the currently running visualization and reset the player.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, under the buttons, we have a player section where the visualization is going to be shown. Initially, the text “Press Play button to start” is shown. As soon as the “Play” button is pressed, we have to remove the text and start the player.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To make the article shorter, only important parts of the code will be shown. You can always find complete code on Github.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The wireframe is complete, and it helps us visualize what the end result should look like, but now it's time to bring it to life.&lt;/p&gt;

&lt;h2&gt;
  
  
  List and elements
&lt;/h2&gt;

&lt;p&gt;When the “Play” button is clicked, we have to generate the list (array) that needs to be sorted, as well as the elements that have to be animated, and insert them into the player container.&lt;/p&gt;

&lt;p&gt;Let's start by creating a random list of numbers that the Bubble Sort algorithm has to sort. A function to quickly generate the list can be created 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;function&lt;/span&gt; &lt;span class="nx"&gt;createData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxNumber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&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="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;maxNumber&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;The function is quite simple; it generates a list that has a certain length of elements. To limit the maximum number that can be generated, &lt;code&gt;maxNumber&lt;/code&gt; is used.&lt;/p&gt;

&lt;p&gt;This generated list of numbers will also be represented using SVG elements. Every list number will have its own corresponding SVG element. By animating these elements, we can visualize how the list itself is being sorted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3Ssm-IlS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r41wqx9ue8sae87ad47q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3Ssm-IlS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r41wqx9ue8sae87ad47q.png" alt="Representation of single number using SVG elements" width="624" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see different SVG elements used to represent one single number from the list. The exact number value is shown using the &lt;code&gt;text&lt;/code&gt; element. This value is then visualized as a &lt;strong&gt;bar&lt;/strong&gt; represented by the &lt;code&gt;rect&lt;/code&gt; element, and finally, the &lt;code&gt;g&lt;/code&gt; element is used to group both &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;rect&lt;/code&gt; elements together so they can be easily animated to the correct positions during sorting.&lt;/p&gt;

&lt;p&gt;Before we can focus on creating SVG elements, there are a couple of variables that we need to take care of. Consider the following image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vo4RiN91--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bfvv2zmgy6iytvlr7k05.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vo4RiN91--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bfvv2zmgy6iytvlr7k05.png" alt="Relation between SVG elements" width="796" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To properly layout elements, we have to define certain variables that describe how the elements are related to each other.&lt;/p&gt;

&lt;p&gt;On the image, you can see that we need to define four different variables as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bar with&lt;/strong&gt; - width of the single bar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bar spacing&lt;/strong&gt; - spacing between neighboring bars.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text offset&lt;/strong&gt; - space between the bar and correlated text.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maximal bar height&lt;/strong&gt; - maximum height that a single bar can reach.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using these variables, we can make sure that our SVG representation of the list looks consistent. This makes things easier when we need to apply animations.&lt;/p&gt;

&lt;p&gt;Since SVG is basically a 2D (two-dimensional) graphic, we have to use the x and y axes to position our elements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Txcm9PVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3g7t1abzr4jxkio8k7i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Txcm9PVS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q3g7t1abzr4jxkio8k7i.png" alt="SVG elements in 2D grid" width="800" height="1025"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the image, you can see how we can position our SVG elements inside the 2D coordinate system. You might notice that the 2D coordinate system on the image looks upside-down. This is because of the scroll behavior in the browser. As you scroll down, the &lt;strong&gt;y&lt;/strong&gt; value is increasing; the more you scroll, the bigger the value of &lt;strong&gt;y&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;To make sure that our elements are initially positioned at the same level on the y axis, we want to put them exactly where the maximum bar height is. From there, we can change the &lt;code&gt;height&lt;/code&gt; property of the &lt;code&gt;rect&lt;/code&gt; element to visualize the value.&lt;/p&gt;

&lt;p&gt;To calculate the value for the x axis, we have to take into account the bar width, bar spacing, and position of the element in the list.&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;function&lt;/span&gt; &lt;span class="nx"&gt;createDOMElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dataList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;barWidth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;barSpacing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;textOffset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxBarHeight&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;settings&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;svgContainer&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;createElementNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://www.w3.org/2000/svg&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="s1"&gt;svg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Create SVG group for each element in the array.
   * SVG group consists of the vertical bar (rect) and text.
   */&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;dataList&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;const&lt;/span&gt; &lt;span class="nx"&gt;barHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataList&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;coordinateX&lt;/span&gt; &lt;span class="o"&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="nx"&gt;barWidth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;barSpacing&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;coordinateY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;maxBarHeight&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;barHeight&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;svgRect&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;createElementNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://www.w3.org/2000/svg&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="s1"&gt;rect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;coordinateY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rx&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="s1"&gt;0.3rem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;width&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;barWidth&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgRect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;height&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;barHeight&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;svgText&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;createElementNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://www.w3.org/2000/svg&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="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;barWidth&lt;/span&gt;&lt;span class="o"&gt;/&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;svgText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;y&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxBarHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;textOffset&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;barHeight&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;svgGroup&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;createElementNS&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://www.w3.org/2000/svg&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="s1"&gt;g&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&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="s1"&gt;bar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;svgGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-index&lt;/span&gt;&lt;span class="dl"&gt;'&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;svgGroup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;coordinateX&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; 0)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;svgGroup&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;svgRect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;svgGroup&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;svgText&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;svgContainer&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;svgGroup&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;svgContainer&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;First, we create a &lt;code&gt;svg&lt;/code&gt; element using the &lt;code&gt;document.createElementNS&lt;/code&gt; API and save it into &lt;code&gt;svgContainer&lt;/code&gt;. We will need it at the end of the function again.&lt;/p&gt;

&lt;p&gt;After that, we loop over the &lt;code&gt;dataList&lt;/code&gt;, which contains numbers that we want to visualize. For each item in the list, we have to do a couple of things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Calculate the x coordinate value using the formula: &lt;em&gt;item index * (bar width + bar spacing)&lt;/em&gt;, and save the result into &lt;code&gt;coordinateX&lt;/code&gt;. We have to use the item index, &lt;code&gt;i&lt;/code&gt;, to make sure that the elements are not stacked on top of each other.&lt;/li&gt;
&lt;li&gt;Calculate the y coordinate value using the formula: &lt;em&gt;maximal bar height - item value&lt;/em&gt;, and save the result into &lt;code&gt;coordinateY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;rect&lt;/code&gt; element and attach the required attributes.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;text&lt;/code&gt; element, attach the required attributes, and set the &lt;code&gt;textContent&lt;/code&gt; property. The &lt;code&gt;x&lt;/code&gt; attribute is set to &lt;em&gt;half of bar width&lt;/em&gt; to keep the text in the center of the bar. And the &lt;code&gt;y&lt;/code&gt; attribute is set to &lt;em&gt;maximal bar height + text offset&lt;/em&gt; to keep it under the bar.&lt;/li&gt;
&lt;li&gt;Create an &lt;code&gt;g&lt;/code&gt; element and attach the required attributes. We use the &lt;code&gt;data-index&lt;/code&gt; attribute to link the &lt;code&gt;g&lt;/code&gt; element with the corresponding item from the list. Also, the &lt;code&gt;transform&lt;/code&gt; attribute is initialized, as it will be used to update the element's position later on.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;rect&lt;/code&gt; and &lt;code&gt;text&lt;/code&gt; elements are then appended to the &lt;code&gt;g&lt;/code&gt; element to keep them grouped with each other.&lt;/li&gt;
&lt;li&gt;Finally, the grouped elements are then appended to the &lt;code&gt;svgContainer&lt;/code&gt; created at the beginning.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Function will return the &lt;code&gt;svgContainer&lt;/code&gt; itself, which can be inserted in the player container when the play button is pressed. With preparation done, we are ready to continue with the animation part.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bubble Sort animation driver
&lt;/h2&gt;

&lt;p&gt;To animate the Bubble Sort algorithm, we cannot just write a function that will do the sorting. We need to be able to control the algorithm and execute side effects at each iteration. To do this, we need to make some kind of “driver”.&lt;/p&gt;

&lt;p&gt;For a driver to properly work, it needs to manage its internal state. Here are the things we need to take care of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Player element - HTML element where the animation player is located.&lt;/li&gt;
&lt;li&gt;Timer id - ID of the currently active timer.&lt;/li&gt;
&lt;li&gt;List - a list of numbers that is currently being sorted.&lt;/li&gt;
&lt;li&gt;Pause - a flag to indicate that the animation is paused.&lt;/li&gt;
&lt;li&gt;Loop index - index of the running loop.&lt;/li&gt;
&lt;li&gt;Remaining repetitions - the total number of remaining repetitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we already know from the wireframe, we have three buttons: &lt;em&gt;play&lt;/em&gt;, &lt;em&gt;pause,&lt;/em&gt; and &lt;em&gt;stop&lt;/em&gt;. This means that the driver needs to be able to properly respond to these buttons. For that, we can create corresponding functions.&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;function&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Default settings&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;maxBarHeight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;barWidth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;barSpacing&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="na"&gt;textOffset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;animationSpeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;listLength&lt;/span&gt;&lt;span class="p"&gt;:&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;// Initial player state&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;playerState&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;playerElement&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;player-wrapper&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&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="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&lt;/span&gt; &lt;span class="o"&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;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;settings&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;settings&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="c1"&gt;// Extend player state before the next animation is started&lt;/span&gt;
        &lt;span class="nx"&gt;playerState&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;playerState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;list&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;createData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listLength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxBarHeight&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="na"&gt;pause&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="na"&gt;loopIndex&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="na"&gt;remainingRepetitions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listLength&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="nx"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Clear scheduled timeout&lt;/span&gt;
      &lt;span class="nx"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="c1"&gt;// Reset player container&lt;/span&gt;
      &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll-x&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;p&amp;gt;Press "Play" button to start&amp;lt;/p&amp;gt;&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="nx"&gt;pause&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;The &lt;code&gt;driver&lt;/code&gt; function returns an object that provides methods for controlling the sorting animation. We can call the specific method when the corresponding button in the UI is clicked.&lt;/p&gt;

&lt;p&gt;You might have noticed that in the &lt;code&gt;play&lt;/code&gt; method, there is a call to the &lt;code&gt;bubbleSort&lt;/code&gt; function. This function implements the Bubble Sort algorithm and controls the sorting animation.&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;function&lt;/span&gt; &lt;span class="nx"&gt;bubbleSort&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;remainingRepetitions&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&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;svgContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getPlayerSvgContainer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;adjustHorizontalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgContainer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We first have to create an SVG container element where the sorting visualization is displayed by calling the &lt;code&gt;getPlayerSvgContainer&lt;/code&gt; function. This container will hold the bars that represent the data being sorted.&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;function&lt;/span&gt; &lt;span class="nx"&gt;getPlayerSvgContainer&lt;/span&gt;&lt;span class="p"&gt;()&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;svgContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&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;svg&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;svgContainer&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;svgContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createDOMElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&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="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgContainer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;svgContainer&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;This function will return the existing &lt;code&gt;svg&lt;/code&gt; element if it is found, or create a new one by calling the &lt;code&gt;createDOMElements&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Next, we have to adjust the horizontal scroll bar in case the &lt;code&gt;svgContainer&lt;/code&gt; width is bigger than the wrapping player container. We can do that by calling the &lt;code&gt;adjustHorizontalScroll&lt;/code&gt; function.&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;function&lt;/span&gt; &lt;span class="nx"&gt;adjustHorizontalScroll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgContainer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Check content width&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playerWrapperWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&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;svgContainerWidth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;svgContainer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clientWidth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Allow horizontal scroll if player wrapper can not show all elements&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;playerWrapperWidth&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;svgContainerWidth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll-x&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;playerElement&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="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;scroll-x&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;So far, so good. Let's continue with our &lt;code&gt;bubbleSort&lt;/code&gt; function.&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;function&lt;/span&gt; &lt;span class="nx"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="c1"&gt;// Get SVG elements for sorting (SVG g elements)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;elementsToSort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgContainer&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="c1"&gt;// Check if list is sorted&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;loopIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;remainingRepetitions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;elementsToSort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;element&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="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;swapped&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;}&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;leftElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getBubbleSortElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;elementsToSort&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to get SVG elements (representing the bars and their labels) from the SVG container. To do so, we can use the &lt;code&gt;Array.from&lt;/code&gt; method by passing the &lt;code&gt;svgContainer.children&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Before we continue, we need to add an exit condition that is only true when the sorting process is complete. We can do that by checking if the current &lt;code&gt;loopIndex&lt;/code&gt; is the same or bigger than the &lt;code&gt;remainingRepetitions&lt;/code&gt;. If this is the case, we can mark all SVG elements as sorted by providing &lt;code&gt;'swapped'&lt;/code&gt; CSS class. If the exit condition is not satisfied, we continue with sorting.&lt;/p&gt;

&lt;p&gt;To know if elements need to swap positions, we have to get two neighboring elements based on the &lt;code&gt;loopIndex&lt;/code&gt; and compare them.&lt;/p&gt;

&lt;p&gt;To get the needed elements, &lt;code&gt;leftElement&lt;/code&gt; and &lt;code&gt;rightElement&lt;/code&gt;, we can call the &lt;code&gt;getBubbleSortElements&lt;/code&gt; function. This function uses the &lt;code&gt;data-index&lt;/code&gt; attribute to match the corresponding element with the item from the list.&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;function&lt;/span&gt; &lt;span class="nx"&gt;getBubbleSortElements&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;svgElements&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&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;leftElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;svgElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;data-index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&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;rightElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;svgElements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;data-index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&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="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightElement&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;To visually indicate which elements are being compared in the current iteration, we do so by adding the CSS class &lt;code&gt;'current'&lt;/code&gt; to them.&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;function&lt;/span&gt; &lt;span class="nx"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="c1"&gt;// Mark elements as current&lt;/span&gt;
  &lt;span class="nx"&gt;leftElement&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="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rightElement&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="nx"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Player is paused, skip sorting for the moment&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;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&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="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;didSwap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performSwapIfNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the elements are marked, it is a good time to handle the eventual &lt;em&gt;pause&lt;/em&gt; event; in other words, if the &lt;em&gt;pause&lt;/em&gt; button is clicked. We can do so by checking &lt;code&gt;playerState.pause&lt;/code&gt; and exiting the function if the &lt;code&gt;pause&lt;/code&gt; property is set.&lt;/p&gt;

&lt;p&gt;When the &lt;em&gt;play&lt;/em&gt; button is pressed again, the &lt;code&gt;pause&lt;/code&gt; property will be set to &lt;code&gt;false&lt;/code&gt;, and the &lt;code&gt;bubbleSort&lt;/code&gt; function will be called again to resume sorting.&lt;/p&gt;

&lt;p&gt;Next, we can finally swap elements if they are out of position. To do so, we call the &lt;code&gt;performSwapIfNeeded&lt;/code&gt; function.&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;function&lt;/span&gt; &lt;span class="nx"&gt;performSwapIfNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightElement&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&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;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&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="k"&gt;return&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;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&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;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&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;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt;

  &lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${(&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&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;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barWidth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barSpacing&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; 0)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;transform&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`translate(&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barWidth&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barSpacing&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt; 0)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&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;rightElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data-index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&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;We pass &lt;code&gt;leftElement&lt;/code&gt; and &lt;code&gt;rightElement&lt;/code&gt; as arguments to the function. In the function, we can take the &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;loopIndex&lt;/code&gt; directly from the &lt;code&gt;playerState&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the item at &lt;code&gt;loopIndex&lt;/code&gt; is smaller than the item at &lt;code&gt;loopIndex + 1&lt;/code&gt;, the function returns &lt;code&gt;false&lt;/code&gt;, indicating that no swap occurred.&lt;/p&gt;

&lt;p&gt;If a swap is needed, we have to update the &lt;code&gt;list&lt;/code&gt; by swapping the positions of the two items in the &lt;code&gt;list&lt;/code&gt;. By updating the &lt;code&gt;transform&lt;/code&gt; attribute of &lt;code&gt;leftElement&lt;/code&gt; and &lt;code&gt;rightElement&lt;/code&gt;, we can adjust horizontal positions to visually reflect the updated order after the swap.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sCvYsoxC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izyypdooz7gyy37m1z69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sCvYsoxC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/izyypdooz7gyy37m1z69.png" alt="Compare and swap elements" width="600" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We also have to update the &lt;code&gt;data-index&lt;/code&gt; attribute to match the corresponding elements with the items from the &lt;code&gt;list&lt;/code&gt;. Finally, the function returns &lt;code&gt;true&lt;/code&gt; to indicate that a swap occurred.&lt;/p&gt;

&lt;p&gt;We now have to visually update affected elements and prepare the player state for the next invocation of the &lt;code&gt;bubbleSort&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Continuing, we have to schedule the timer for the next invocation of the &lt;code&gt;bubbleSort&lt;/code&gt; function, update the player state, and set the correct CSS classes on the affected elements from the previous invocation.&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;// Update loop index&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;didSwap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performSwapIfNeeded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;timerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt;&lt;span class="o"&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;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remainingRepetitions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Current repetition has finished&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;didSwap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;leftElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&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="s1"&gt;bar swapped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;rightElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;leftElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;rightElement&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;class&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="s1"&gt;bar swapped&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="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;remainingRepetitions&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;playerState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loopIndex&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="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;// Current repetition still in progress&lt;/span&gt;
      &lt;span class="nx"&gt;leftElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;rightElement&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="nx"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;current&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="nx"&gt;bubbleSort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;animationSpeed&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;To schedule the next step of the sorting animation we can use &lt;code&gt;setTimeout&lt;/code&gt; API. The timeout time will be set to the value of &lt;code&gt;settings.animationSpeed&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Let's focus on callback function that is triggered by &lt;code&gt;setTimeout&lt;/code&gt;. First thing we have to do is to  increment the &lt;code&gt;loopIndex&lt;/code&gt; to move to the next step in the sorting process.&lt;/p&gt;

&lt;p&gt;We can now check if the current repetition has finished and updates the visual representation of the elements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Depending on the &lt;code&gt;didSwap&lt;/code&gt; flag we can update &lt;code&gt;leftElement&lt;/code&gt; and &lt;code&gt;rightElement&lt;/code&gt; by removing or setting &lt;code&gt;'current'&lt;/code&gt; and  &lt;code&gt;'swapped'&lt;/code&gt; CSS classes.&lt;/li&gt;
&lt;li&gt;Lastly we can decrement the &lt;code&gt;remainingRepetitions&lt;/code&gt; counter and resets &lt;code&gt;loopIndex&lt;/code&gt; to 0.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the current repetition is still in progress, we just have to remove the &lt;code&gt;'current'&lt;/code&gt; class from both &lt;code&gt;leftElement&lt;/code&gt; and &lt;code&gt;rightElement&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When the player state and visual elements are properly updated, we can call &lt;code&gt;bubbleSort&lt;/code&gt; recursively to continue the animation with the next comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the animation driver
&lt;/h2&gt;

&lt;p&gt;To use the driver, we just need to call &lt;code&gt;driver&lt;/code&gt; function which will return interface/object that contains &lt;code&gt;play&lt;/code&gt;, &lt;code&gt;pause&lt;/code&gt; and &lt;code&gt;stop&lt;/code&gt; methods.&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;// Get DOM elements&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;playButtonElement&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;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;play-button&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;pauseButtonElement&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;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;pause-button&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;stopButtonElement&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;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;stop-button&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;listLengthInputElement&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;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;list-length&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;animationSpeedInputElement&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;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;animation-speed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Initialize driver to run Bubble Sort visualization&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bubbleSortDriver&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Call driver.play when play button is clicked&lt;/span&gt;
&lt;span class="nx"&gt;playButtonElement&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;click&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="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;play&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;listLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listLengthInputElement&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="na"&gt;animationSpeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animationSpeedInputElement&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="c1"&gt;// Call driver.stop when stop is clicked&lt;/span&gt;
&lt;span class="nx"&gt;stopButtonElement&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;click&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="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Call driver.pause when pause is clicked&lt;/span&gt;
&lt;span class="nx"&gt;pauseButtonElement&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;click&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="nx"&gt;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pause&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;We just need to make sure to call correct driver method depending the button that was clicked. Driver encapsulates all logic related to managing Bubble Sort visualization under the hood and exposes simple API that can be easily used.&lt;/p&gt;

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

&lt;p&gt;In this article I tried to give a concrete example on how to use SVG elements to actually visualize data and algorithm in action. We used SVG elements to visualize Bubble Sort algorithm in action by creating an animation driver that can be control using buttons.&lt;/p&gt;

&lt;p&gt;I hope you have a better idea about how to use SVG graphic and that this article was helpful is one way or another.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://wannabedev.io/"&gt;wannabedev.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>svg</category>
      <category>algorithms</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Everything you need to know about JSON Web Token</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Tue, 05 Sep 2023 18:13:00 +0000</pubDate>
      <link>https://dev.to/rmmgc/everything-you-need-to-know-about-json-web-token-5864</link>
      <guid>https://dev.to/rmmgc/everything-you-need-to-know-about-json-web-token-5864</guid>
      <description>&lt;p&gt;Ready to read about JSON Web Token so much that it becomes boring? Well, me neither, but here we are.&lt;/p&gt;

&lt;p&gt;Before we start, keep in mind that this is a more conceptual guide and includes almost no code examples. If you are looking for an article that explains how to use JWT for a specific use case with a specific language implementation, you are in the wrong place. With that out of the way, let's get started.&lt;/p&gt;

&lt;p&gt;Upss, I almost forgot, here is table of contents so you can jump to different topics quickly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
What is JWT

&lt;ul&gt;
&lt;li&gt;Payload&lt;/li&gt;
&lt;li&gt;Header&lt;/li&gt;
&lt;li&gt;Signature&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Token Claims

&lt;ul&gt;
&lt;li&gt;Registered Claims&lt;/li&gt;
&lt;li&gt;Public Claims&lt;/li&gt;
&lt;li&gt;Private Claims&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Formats

&lt;ul&gt;
&lt;li&gt;JWS (JSON Web Signature)&lt;/li&gt;
&lt;li&gt;JWE (JSON Web Encryption)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
How It Works

&lt;ul&gt;
&lt;li&gt;Token Generation&lt;/li&gt;
&lt;li&gt;Token Verification&lt;/li&gt;
&lt;li&gt;Token Expiration&lt;/li&gt;
&lt;li&gt;Token Revocation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
HS256 Algorithm

&lt;ul&gt;
&lt;li&gt;Pros&lt;/li&gt;
&lt;li&gt;Cons&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
RS256 Algorithm

&lt;ul&gt;
&lt;li&gt;RSA encryption&lt;/li&gt;
&lt;li&gt;JWT signature generation&lt;/li&gt;
&lt;li&gt;JWT signature verification&lt;/li&gt;
&lt;li&gt;Pros&lt;/li&gt;
&lt;li&gt;Cons&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Benefits of JWT&lt;/li&gt;
&lt;li&gt;
JWT and Authentication

&lt;ul&gt;
&lt;li&gt;Authentication server&lt;/li&gt;
&lt;li&gt;Application server&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;JWT and Authorization&lt;/li&gt;
&lt;li&gt;Best practices&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is JWT &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;JWT is an open industry standard (&lt;a href="https://www.rfc-editor.org/rfc/rfc7519"&gt;RFC 7519&lt;/a&gt;) that defines compact, simple and self-contained way to &lt;strong&gt;securely&lt;/strong&gt; share information between two entities. As the name implies, information contained in JWT is provided in JSON format.&lt;/p&gt;

&lt;p&gt;JWT is specifically made to be used in environments like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization"&gt;HTTP Authorization&lt;/a&gt; headers and URI query parameters. This makes JWT a great option for authentication and authorization purposes as well as information exchange. It consists of three different components: the header, payload, and signature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Uw4YjBlj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoyiicl329bfwx8ntczy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Uw4YjBlj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uoyiicl329bfwx8ntczy.png" alt="JWT components: header, payload and signature" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Header and payload are formatted using JSON format, while signature usually get generated one way or another. Every component serves a specific purpose, and JWT is not complete if either of these components are missing.&lt;/p&gt;

&lt;p&gt;We will talk much more about JWT components, but for now, let's introduce them so we have an idea of what they look like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Payload &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The payload holds the actual data that we want to secure and transmit using JWT. It can literally be anything. Take a look at the following 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="s2"&gt;John Doe&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="s2"&gt;moderator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload is written in JSON format and includes key-values pairs, also known as claims.&lt;/p&gt;

&lt;h3&gt;
  
  
  Header &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The header component of a JWT contains metadata about the token and the cryptographic algorithms used to secure it.&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alg&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="s2"&gt;HS256&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="s2"&gt;typ&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="s2"&gt;JWT&lt;/span&gt;&lt;span class="dl"&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 typically consists of two parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;typ&lt;/code&gt; (Type): declare the media type.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;alg&lt;/code&gt; (Algorithm): signing algorithm used to sign JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also &lt;a href="https://datatracker.ietf.org/doc/html/rfc7515#section-4"&gt;more properties&lt;/a&gt; that you can specify in the header, but only &lt;code&gt;alg&lt;/code&gt; is required. The header is very important, especially for token verification, since it provides information about the algorithm used to sign JWT.&lt;/p&gt;

&lt;h3&gt;
  
  
  Signature &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The signature is the final component of a JWT. It is generated by combining the encoded header, encoded payload, and a secret key known only to the entity responsible for issuing the token.&lt;/p&gt;

&lt;p&gt;Wait, slow down. Generated, encoded, secret key? What does it even mean? I know this sounds like a lot, but just keep going, and everything will come together.&lt;/p&gt;

&lt;p&gt;That being said, the signature ensures the &lt;strong&gt;integrity&lt;/strong&gt; and &lt;strong&gt;authenticity&lt;/strong&gt; of the token. It is the &lt;strong&gt;only thing&lt;/strong&gt; that can be used to prove that the token can be trusted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Token Claims &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;When we talked about the payload, we said that it consists of key-value pairs, also known as &lt;strong&gt;claims&lt;/strong&gt;. Well, this is exactly what token claims are: key-value pairs that contain pieces of information about the subject that the token is issued for.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The payload must not include duplicate keys (claim names).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are three types of JWT claims: &lt;strong&gt;registered&lt;/strong&gt; claims, &lt;strong&gt;public&lt;/strong&gt; claims, and &lt;strong&gt;private&lt;/strong&gt; claims. None of the mentioned claims are mandatory or required in the payload.&lt;/p&gt;

&lt;h3&gt;
  
  
  Registered Claims &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Registered claims are defined by JWT specification and have standardized meanings. These claims provide useful information for interoperability and common use cases. In total, there are 7 registered claims, as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;iss&lt;/code&gt; (Issuer): identifies the entity that issued the JWT.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sub&lt;/code&gt; (Subject): represents the subject of the JWT, typically the user or client it belongs to.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;aud&lt;/code&gt; (Audience): identifies the recipients that the JWT is intended for.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;exp&lt;/code&gt; (Expiration Time): the expiration time on or after which the JWT should not be accepted anymore.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;nbf&lt;/code&gt; (Not Before): the time before which JWT must not be accepted.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;iat&lt;/code&gt; (Issued At): indicates the time at which the JWT was issued.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jti&lt;/code&gt; (JWT ID): unique identifier for the JWT.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using registered claims helps ensure consistency and understanding across different systems that consume JWTs. This is important when working with third-party services, for example.&lt;/p&gt;

&lt;h3&gt;
  
  
  Public Claims &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Public claims are custom claims that are defined by developers. They are used to convey application-specific information and can vary based on the requirements of the system.&lt;/p&gt;

&lt;p&gt;They should be registered with an appropriate authority or namespace to avoid conflicts. You can see a list of available public claims in the &lt;a href="https://www.iana.org/assignments/jwt/jwt.xhtml#claims"&gt;IANA JSON Web Token Claims Registry&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Public claims enable developers to include additional context or data within the JWT to support their application's specific needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Private Claims &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Private claims are custom claims that are specific to a particular application or organization. They are usually not meant to be used or understood by other parties. Private claims allow developers to include proprietary or internal information within the JWT.&lt;/p&gt;

&lt;p&gt;Private claims are useful for carrying application-specific data without worrying about potential conflicts.&lt;/p&gt;

&lt;p&gt;This all might seem unnecessary, but keep in mind that there are a lot of big companies and services that rely on these claims and recommendations to be followed. They provide the necessary context for authentication, authorization, and any additional data required by the consumer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formats &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before we can continue further, you need to understand that JWT is just an abstraction built on top of already-existing industry standards. These standards are JWS (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7515"&gt;JSON Web Signature&lt;/a&gt;) and JWE (&lt;a href="https://datatracker.ietf.org/doc/html/rfc7516"&gt;JSON Web Encryption&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q16mAoTJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80apaf21xdbmx7s7ut6o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q16mAoTJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/80apaf21xdbmx7s7ut6o.png" alt="JWT formats: JWS and JWE" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that JWTs can be represented in two different formats: JWS or JWE. The information about which of these formats is used is presented in the JWT header.&lt;/p&gt;

&lt;p&gt;Still remember this &lt;code&gt;alg&lt;/code&gt; property in the header that defines which algorithm is used to secure the token? Well, it turns out that JWS and JWE have different algorithms. So, just by specifying the algorithm, you are also selecting the format itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  JWS (JSON Web Signature) &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;JWS is by far the most common way to represent JWT. Also, in the rest of this article, we will focus only on JWT represented using JWS.&lt;/p&gt;

&lt;p&gt;In JWS format, the token is signed using an encoded header, encoded payload, and secret key (password). This process will generate a JWT signature. The signature provides authenticity and integrity to the token.&lt;/p&gt;

&lt;p&gt;Look at the payload that we had before.&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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="s2"&gt;John Doe&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="s2"&gt;moderator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a signature is created and a token is shared, this payload will be completely visible to everyone who gets the token.&lt;/p&gt;

&lt;p&gt;You might ask yourself, why is this token useful when everyone can see its payload? The important thing is that you should &lt;strong&gt;not share&lt;/strong&gt; any sensitive data in the payload. Even if a potential attacker gets his hands on the token, he will not be able to extract any meaningful information from the payload.&lt;/p&gt;

&lt;p&gt;Obviously, JWS has its own advantages and disadvantages, but we will stop here, or this part might get too big very quickly.&lt;/p&gt;

&lt;h3&gt;
  
  
  JWE (JSON Web Encryption) &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The payload of a JWE token is encrypted using a private key (asymmetric encryption), and only entities with the corresponding public key can decrypt and verify the token.&lt;/p&gt;

&lt;p&gt;So, in practical terms, the JWT payload will be encrypted when using JWE format and completely visible when using JWS format.&lt;/p&gt;

&lt;p&gt;JWE is useful when the payload contains sensitive information that should be kept confidential. But for most use cases, it is not required.&lt;/p&gt;

&lt;p&gt;Remember, in this article, when we say JWT, it means JWT in the form of JWS. It is the most commonly used form and the one you will most likely encounter much more often.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We talked a lot about more theoretical and perhaps boring stuff. Let's switch our focus to what actually matters and explore how JWT actually works.&lt;/p&gt;

&lt;p&gt;Like almost any token, it is important to consider how to &lt;strong&gt;generate&lt;/strong&gt;, &lt;strong&gt;verify&lt;/strong&gt;, &lt;strong&gt;revoke,&lt;/strong&gt; and &lt;strong&gt;expire&lt;/strong&gt; JWT. Let's start by exploring token generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Generation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Token generation describes the process of creating JWT. It usually involves a couple of steps that we will go through.&lt;/p&gt;

&lt;p&gt;The first thing we need to do is define the payload for our token. It can literally be anything; depending on specific usage, different claims can be provided. The payload might 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&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="s2"&gt;John Doe&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="s2"&gt;iat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1687716785&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;exp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1741651200&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that we added some registered claims like &lt;code&gt;iat&lt;/code&gt; and &lt;code&gt;exp&lt;/code&gt;, but not all of them. It is up to you to decide which claims to add.&lt;/p&gt;

&lt;p&gt;With that out of the way, we need to consider which signing algorithm to use for our JWT. There are many types of algorithms available, but the most common are &lt;strong&gt;HS256&lt;/strong&gt; and &lt;strong&gt;RS256&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We will talk more about the HS256 and RS256 algorithms a little bit later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For now, let's keep it simple and select &lt;strong&gt;HS256&lt;/strong&gt; as the signing algorithm for our JWT. With that decision out of the way, we can also create a header 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="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alg&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="s2"&gt;HS256&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="s2"&gt;typ&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="s2"&gt;JWT&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we have to generate the signature. Remember, the signature is the part that actually ensures the integrity and authenticity of the token and is the only thing that can be used to prove that the token can be trusted. &lt;/p&gt;

&lt;p&gt;To generate signature, we have to combine header and payload. But, there is one more thing we have to do before that. We can not just leave them in plain JSON format. After all, the token will be transferred via HTTP headers or URI query parameters and it has to be safe to use in such environments.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://datatracker.ietf.org/doc/html/rfc4648#section-5"&gt;base64url&lt;/a&gt; comes into play. It is basically the same encoding as base64, but it uses a URL and filename-safe alphabet making it perfect for applications where sharing via URL is important.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7FNO7R5g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y38pfj0vlfyn9p83paez.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7FNO7R5g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y38pfj0vlfyn9p83paez.png" alt="Process of JWT generation using the HS256 algorithm" width="800" height="518"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Header and payload first have to be converted to &lt;code&gt;UTF-8&lt;/code&gt; strings, which are basically a stringified version of the JSON format. This string can then be encoded using &lt;code&gt;base64url&lt;/code&gt;, which will produce an encoded version of the header and payload.&lt;/p&gt;

&lt;p&gt;We can now use the encoded header and payload to generate the signature. Here is where things could change a little bit. Depending on the algorithm specified in the header via the &lt;code&gt;alg&lt;/code&gt; property, signature generation might be a little bit different.&lt;/p&gt;

&lt;p&gt;Since we decided to use the HS256 algorithm, we have to provide the &lt;strong&gt;symmetric secret key&lt;/strong&gt;. It is obviously important to choose a hard-to-guess sequence of characters. For our arbitrary example, let's just say that the secret key is the string &lt;code&gt;super-secret&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A symmetric secret key is used both to sign the token and to verify it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Finally, we can use the HS256 (&lt;a href="https://en.wikipedia.org/wiki/HMAC"&gt;HMAC-SHA256&lt;/a&gt;) cryptographic hash function to generate the signature. This function is already implemented for probably every language you can think of.&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;HMACSHA256&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;encoded_header&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;encoded_payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;super-secret&lt;/span&gt;&lt;span class="dl"&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 output of this operation is going to be our signature, also known as HMAC (Hash-Based Message Authentication Code), which is a form of digital signature. The generated signature also has to be &lt;code&gt;base64url&lt;/code&gt; encoded.&lt;/p&gt;

&lt;p&gt;Lastly, we have to create a compact version of the JWT. To do so, we need to combine the encoded header, payload, and signature separated by &lt;code&gt;.&lt;/code&gt; (period) character.&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;// base64url encoded JWT components&lt;/span&gt;
&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE2ODc3MTY3ODUsImV4cCI6MTc0MTY1MTIwMH0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="nx"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;zrwE8dR_RbbkjKsxul-U8cL9FUcMjeCvOSnk6obd0Xo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// JWT&lt;/span&gt;
&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;signature&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the final JWT is a string representation of the encoded header, payload, and signature. This compact form of the JWT is actually what we can use in our applications and APIs. &lt;/p&gt;

&lt;p&gt;On the first glance, there might be a lot of moving parts and things we have to consider, but it is not that hard. If we put it all together into a single image, it might look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wFYwSWIo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxh2mtf7hav7eq8pzd3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wFYwSWIo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rxh2mtf7hav7eq8pzd3x.png" alt="Process of JWT generation using the HS256 algorithm" width="800" height="729"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have covered a lot of things just now. Take your time and read it again if something is not clear. Here are the most important things related to token generation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prepare the token payload by adding the needed claims. Try to add as many registered claims as possible.&lt;/li&gt;
&lt;li&gt;Decide on which algorithm to use.&lt;/li&gt;
&lt;li&gt;Populate the token header by providing a minimum &lt;code&gt;alg&lt;/code&gt; claim.&lt;/li&gt;
&lt;li&gt;Make sure to choose a strong secret key and keep it safe.&lt;/li&gt;
&lt;li&gt;Encode the header and payload using &lt;code&gt;base64url&lt;/code&gt; and concatenate them using a &lt;code&gt;.&lt;/code&gt; period.&lt;/li&gt;
&lt;li&gt;Create a token signature by running the HMAC-SHA256 hash function on the concatenated header and payload together with the secret key.&lt;/li&gt;
&lt;li&gt;Encode the token signature using &lt;code&gt;base64url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Generate compact form by concatenating the encoded header, payload, and signature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind that token generation will be slightly different depending on the algorithm you choose to use. Here, we have used HMAC-SHA256 by specifying HS256 in the header &lt;code&gt;alg&lt;/code&gt; property. We will talk more about HS256 and RS256 algorithms later in this guide.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Verification &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It's time to explore the other end of the spectrum: &lt;em&gt;token verification&lt;/em&gt;. Before we can verify the token, we need to know which algorithm was used to digitally sign it.&lt;/p&gt;

&lt;p&gt;To do so, we can take the header part of the token and inspect the &lt;code&gt;alg&lt;/code&gt; property. More often than not, we would know this information ahead of time since we could get it from the entity that generated the token. Anyway, we know that the algorithm used is actually HS256, which means that the token was signed using HMAC-SHA256.&lt;/p&gt;

&lt;p&gt;The only way to confirm that the token can be trusted is to &lt;strong&gt;generate&lt;/strong&gt; a control signature and &lt;strong&gt;compare&lt;/strong&gt; it to the signature obtained from the token.&lt;/p&gt;

&lt;p&gt;Remember, a token consists of an encoded header, payload, and signature separated by the &lt;code&gt;.&lt;/code&gt; period character. As a reference, look at the token that we generated in the previous section:&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;// Separated with a new line for an easier overview.&lt;/span&gt;
&lt;span class="nx"&gt;eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;eyJuYW1lIjoiSm9obiBEb2UiLCJpYXQiOjE2ODc3MTY3ODUsImV4cCI6MTc0MTY1MTIwMH0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;zrwE8dR_RbbkjKsxul&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;U8cL9FUcMjeCvOSnk6obd0Xo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is one more very important thing that we need to generate the signature: &lt;em&gt;the secret key&lt;/em&gt;. The &lt;strong&gt;same secret key&lt;/strong&gt; has to be used to generate and verify the token. Otherwise, the verification step would fail. So, when using HS256, you need to make sure that the secret key is available at the point where the token is generated and at the point where the token is verified.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---RNh7JqK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kh42yb9rc59nne4zh4cp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---RNh7JqK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kh42yb9rc59nne4zh4cp.png" alt="Process of JWT verification using the HS256 algorithm" width="800" height="795"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have all the required data, we can finally verify the token. First, we split the token into three components: the encoded header, encoded payload, and encoded signature. Next, we concatenate the encoded header and encoded payload using &lt;code&gt;.&lt;/code&gt; period.&lt;/p&gt;

&lt;p&gt;The resulting string is taken and passed to HMAC-SHA256 together with the secret key to generate the control signature. We also need to make sure that the control signature is encoded using &lt;code&gt;base64url&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we can compare the control signature with the signature from the token and check if they are an exact match. If they are the same, we know that the token can be trusted and that no one has tried to change its payload. If the signatures do not match, the token is invalid, and someone has tried to compromise it.&lt;/p&gt;

&lt;p&gt;It is also important to check the claims provided in the payload. To do so, we first have to decode the payload using the revers action of base64url. Depending on the requirements, token claims can be used to further fine-tune the verification process by ensuring that they meet the required criteria.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Expiration &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;JWTs can have a limited lifespan to enhance security and mitigate the risks associated with long-lived tokens. It is very important to create tokens in such a way that they can expire. If expiration time is not taken into consideration, in theory, tokens could be valid indefinitely.&lt;/p&gt;

&lt;p&gt;Every JWT should include an expiration time provided via the &lt;code&gt;exp&lt;/code&gt; claim, which indicates the timestamp after which the token is considered invalid.&lt;/p&gt;

&lt;p&gt;However, just adding an &lt;code&gt;exp&lt;/code&gt; claim is not enough. The token verification strategy also needs to be implemented in such a way that the &lt;code&gt;exp&lt;/code&gt; claim is &lt;strong&gt;always checked&lt;/strong&gt;. All expired tokens should be &lt;strong&gt;rejected&lt;/strong&gt;, no matter what.&lt;/p&gt;

&lt;h3&gt;
  
  
  Token Revocation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We just talked about expiration and the &lt;code&gt;exp&lt;/code&gt; claim, but it cannot help us in all situations. What happens if we &lt;strong&gt;lose&lt;/strong&gt; or &lt;strong&gt;leak&lt;/strong&gt; a valid token that has not yet expired? Anyone in token possession could use it to access restricted resources. This is where revocation and &lt;strong&gt;revocation strategies&lt;/strong&gt; come into play.&lt;/p&gt;

&lt;p&gt;Token revocation is a big issue for JWT since they &lt;strong&gt;are stateless&lt;/strong&gt;. This means the token itself holds all the data necessary for its verification. The entity that created the token does not need to keep any token-related state. So, whenever a token is lost, it will continue to be valid until it expires.&lt;/p&gt;

&lt;p&gt;What can we do to invalidate these tokens? The common way to do it is to create some kind of storage for revoked tokens. This storage should always be checked during token verification. If the token is found in the storage, it should be &lt;strong&gt;marked as revoked&lt;/strong&gt;, and access should be &lt;strong&gt;denied&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With this approach, a token does not have to expire to become invalid. As soon as it's added to the list of revoked tokens, it is basically useless since its verification will fail.&lt;/p&gt;

&lt;p&gt;There are also different strategies to manage the revocation process, but that is not the topic of this article. If you are curious, I encourage you to explore it on your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  HS256 Algorithm &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;As we have said many times before, the security of JWT mainly depends on the type of algorithm we choose to use. So, let's check out HS256 in more detail.&lt;/p&gt;

&lt;p&gt;HS256, which stands for HMAC-SHA256, is one of the popular signing algorithms used in JWT. HMAC (&lt;a href="https://en.wikipedia.org/wiki/HMAC"&gt;Hash-based Message Authentication Code&lt;/a&gt;) is a &lt;strong&gt;symmetric cryptographic algorithm&lt;/strong&gt; that uses a &lt;strong&gt;shared secret key&lt;/strong&gt; to generate a hash-based MAC (Message Authentication Code), also known as HMAC. Using a shared key means that the same key has to be used to sign and verify the token.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We have already talked about signature generation and verification using the HS256 algorithm.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I will not go into details about how this algorithm generates a token signature. If you want to know how it works under the hood, read about HMAC, hashing functions, and SHA-256. They all play a role here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;HS256 is &lt;strong&gt;computationally efficient&lt;/strong&gt; and performs well in terms of generating and verifying signatures. The algorithm is relatively fast and can handle a high volume of token operations.&lt;/p&gt;

&lt;p&gt;Implementing HS256 is &lt;strong&gt;straightforward and simple&lt;/strong&gt;. It only requires a shared secret key between the issuer and the recipient.&lt;/p&gt;

&lt;p&gt;I would like to add more pros, but realistically, compared to RS256, there are not many left on the table. That being said, HS256 is still a fine algorithm to use if we take special care about the cons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;Even if it seems like an impossible task, HS256 signatures can still be &lt;strong&gt;brute-forced&lt;/strong&gt;. This mostly happens if the chosen secret key is weak and easily guessable.&lt;/p&gt;

&lt;p&gt;Maybe the biggest weakness is the &lt;strong&gt;existence of a symmetric secret key&lt;/strong&gt; that has to be shared between issuer and receiver and any other entity that is using JWT. This comes with a lot of issues related to the management of secret keys and token revocation.&lt;/p&gt;

&lt;p&gt;The secret key contributes to the &lt;strong&gt;difficult key rotation&lt;/strong&gt;. Key rotation requires the secret key to be changed on every entity that is using JWT. It becomes increasingly hard and error-prone based on the number of entities relying on the secret key, as you have to update the secret key for each one of them.&lt;/p&gt;

&lt;p&gt;Another issue is the &lt;strong&gt;lack of separation&lt;/strong&gt; between token generation and token verification. When using HS256, every entity can both generate and verify a token, and those actions cannot be separated. This increases the chances of a secret key being stolen since there are just more places where it could happen.&lt;/p&gt;

&lt;p&gt;I think you get the point. In the long run and in more complex systems, HS256 can cause some really serious security concerns. Luckily for us, RS256 can solve all these problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  RS256 Algorithm &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;RS256, which stands for RSA-SHA256, is another widely used algorithm for signing JWTs. RS256 is based on &lt;a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)"&gt;asymmetric cryptography&lt;/a&gt;, utilizing a key pair consisting of a private key for signing and a corresponding public key for verification.&lt;/p&gt;

&lt;p&gt;I know there are a lot of different things going on: RSA, SHA256, cryptography, private and public keys. What is all of that?&lt;/p&gt;

&lt;p&gt;Well, let's say that many smart people have come together to improve the security of the Internet. This is how we got all of these concepts, algorithms, and implementations. They are by no means only used in JWT but rather in many different applications, but that is a topic for another time.&lt;/p&gt;

&lt;p&gt;To keep it concise, we will explore how RS256 works at a higher level. We will not go into too many details, but it will be just enough for you to grasp the concept.&lt;/p&gt;

&lt;p&gt;At the end, we only need this digital signature for our token, so we can assume that the final product of the RS256 algorithm is just that: a digital signature that we can append to our token.&lt;/p&gt;

&lt;h3&gt;
  
  
  RSA encryption &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As RS256 uses the RSA asymmetric cryptography algorithm and RSA keys, we have to talk about them a little bit. This will be a very short introduction to RSA encryption, and I encourage you to explore more.&lt;/p&gt;

&lt;p&gt;RSA uses a key pair consisting of two correlated keys: private and public. A private key should always be kept in a safe place and should only be used for encryption. A public key can be shared with anyone and should only be used for decryption.&lt;/p&gt;

&lt;p&gt;So what the private key encrypts, the correlated public key is able to decrypt. This is very important, as it allows the private key to stay safe since it's not required for decryption. Let's examine how it translates to the process of generating JWT signatures.&lt;/p&gt;

&lt;h3&gt;
  
  
  JWT signature generation &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We said before that, depending on the chosen algorithm, the process of generating a signature might be slightly different. It's time to explore what it looks like for RS256.&lt;/p&gt;

&lt;p&gt;First, we need an RSA key pair. Since RSA is a very common and widely used algorithm, there is an official implementation of it in every common programming language. So we do not have to write it from scratch but rather use the existing implementation to generate the key pair. For now, let's assume that we have the needed key pair.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BotJHtG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5spblld8jrw1cz5v1rox.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BotJHtG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5spblld8jrw1cz5v1rox.png" alt="Process of generating the signature using the RS256 algorithm" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can take an encoded header and encoded payload and hash them using SHA256. The output of this hashing function is by no means secure. It can be easily recreated by the attacker using the same header and payload taken from the token itself.&lt;/p&gt;

&lt;p&gt;To make it secure, we have to take the hash output and &lt;strong&gt;encrypt&lt;/strong&gt; it using the RSA &lt;strong&gt;private key&lt;/strong&gt;. This will produce an &lt;strong&gt;RS256 digital signature&lt;/strong&gt;. Before adding it to the token, the generated digital signature needs to be encoded using &lt;code&gt;base64url&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  JWT signature verification &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;When doing verification of the RS256 signature, we cannot generate exactly the same signature as we could for the HS256 algorithm. For that, we would need to have a private key, which should only be available to the entity that generates the token.&lt;/p&gt;

&lt;p&gt;Instead, we can use a &lt;strong&gt;public key&lt;/strong&gt;, available at the &lt;strong&gt;point of verification&lt;/strong&gt;, to help us determine if the signature is valid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LpFI7SsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ia7z5waz8iewxtm5m40h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LpFI7SsT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ia7z5waz8iewxtm5m40h.png" alt="Process of verifying the signature using the RS256 algorithm" width="800" height="614"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We first need to take the encoded header and encoded payload, concatenate them with a &lt;code&gt;.&lt;/code&gt; period, and pass the result to the SHA256 hashing function to &lt;strong&gt;generate the hash&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Do you still remember what we can do with the public key? That's right, we can take the signature from the token, decode it, and &lt;strong&gt;decrypt it&lt;/strong&gt; using &lt;strong&gt;the public&lt;/strong&gt; key. As a result, we will get the original &lt;strong&gt;signature hash&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now we can compare our &lt;strong&gt;generated hash&lt;/strong&gt; with the &lt;strong&gt;hash from the signature&lt;/strong&gt;. If they are the same, we can conclude that the signature is valid and can be trusted.&lt;/p&gt;

&lt;p&gt;Anyone could have calculated that hash, but the decryption process to get the original signature hash from the token would only work if the token signature was encrypted with the matching RSA private key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pros &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;As you might have noticed already, RS256 provides &lt;strong&gt;higher security&lt;/strong&gt; and &lt;strong&gt;resistance&lt;/strong&gt; to brute-force attacks. This makes it probably impossible for attackers to forge signatures.&lt;/p&gt;

&lt;p&gt;Compared to HS256, there is an added RSA &lt;strong&gt;private&lt;/strong&gt; and &lt;strong&gt;public&lt;/strong&gt; key pair, one for encrypting and one for decrypting data. This eliminates the need for a shared secret key, which caused a lot of security concerns with the HS256 algorithm.&lt;/p&gt;

&lt;p&gt;Relatively &lt;em&gt;simple&lt;/em&gt; &lt;strong&gt;key rotations&lt;/strong&gt; can be executed using RS256. If the private key is compromised, a new RSA key pair can be quickly created, and the public key can be distributed immediately to all relevant entities.&lt;/p&gt;

&lt;p&gt;One nice &lt;em&gt;side effect&lt;/em&gt; of using a public and private key pair is that it provides great &lt;strong&gt;separation of concerns&lt;/strong&gt;. With RS256, the private key should only be available to the entity that handles token generation, while the public key is available to the entity that has to perform token verification. This greatly increases security by reducing the exposure of private keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cons &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;There is not much &lt;em&gt;bad&lt;/em&gt; going on with the RS256 algorithm. However, if we want to be nitpicky, there are some things to consider.&lt;/p&gt;

&lt;p&gt;Using RS256 can introduce &lt;strong&gt;computational complexity&lt;/strong&gt; since it involves operations like encryption and decryption, which can be resource-intensive when dealing with long messages. But this is also not a major concern since it is only required to encrypt or decrypt the signature hash, not the whole token.&lt;/p&gt;

&lt;p&gt;Some might say that &lt;strong&gt;key management&lt;/strong&gt; could cause some concerns related to the secure generation, storage, and distribution of RSA key pairs. I think it's a valid point, but as with any credentials, you have to proceed with care and be aware of related risks.&lt;/p&gt;

&lt;p&gt;As a last note, compared to HS256, we could say that it is &lt;strong&gt;marginally harder&lt;/strong&gt; to implement JWT using RS256, mainly because of asymmetric cryptography and RSA key pairs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of JWT &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;After reading all of this, it might still not be clear what the benefits of JWT are compared to other forms of authentication. JWT has gained widespread popularity as a secure and efficient method for transmitting data between parties because of the benefits it provides, so let's explore some of them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Industry standard&lt;/strong&gt; - 
JWT was created as an industry standard, which further encourages its usage. Being an industry standard ensures interoperability across different platforms, programming languages, and frameworks. Developers can confidently implement JWT-based solutions, knowing that they will work seamlessly across different technologies.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compact&lt;/strong&gt; - 
The less data you send over the Internet, the better. JWT fits nicely because of its compact form. When encoded, it can easily be sent via URL query parameters or HTTP Headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong security&lt;/strong&gt; - 
Tokens are digitally signed, which prevents attackers from modifying token content. Depending on the algorithm used in signature creation, asymmetric keys can be used to further improve security.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless&lt;/strong&gt; - 
The token itself contains all the data necessary for it to be verified, which means that the server doesn't need to store any session information. This eliminates the need for server-side session management and improves scalability.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single Sign-On (SSO) capable&lt;/strong&gt; - 
JWT is widely used in SSO systems. Once a user logs in and receives a JWT, they can use the same token to access multiple applications or services without the need for separate authentication. This seamless user experience simplifies the login process and enhances user productivity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Customizable&lt;/strong&gt; - 
JWT supports custom claims, allowing for the inclusion of additional information relevant to the application's specific requirements. These custom claims can be used to convey application-specific data, user preferences, or any other necessary information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you can grasp why JWT is so popular and widely used by looking at the listed benefits. With all of its benefits, JWT is challenging other forms of authentication and authorization and gaining ever-growing support.&lt;/p&gt;

&lt;h2&gt;
  
  
  JWT and Authentication &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We know by now that JWT can be used for user authentication, but how exactly does that work? Depending on the application requirements, there are different ways to implement user authentication.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This section will include code snippets written in JavaScript. Node, the JavaScript runtime, can be used to run the snippets.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's assume that we want to set up user authentication for our application. We will have the authentication server responsible for authenticating users and generating JWTs, and the application server that will verify JWT and handle requests from the application client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MfGMv5Ix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ayihdwl6zyfn2gkc8iqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MfGMv5Ix--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ayihdwl6zyfn2gkc8iqe.png" alt="JWT and authentication" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the image above, you can see the basic authentication flow for our application. The application client represents the user interface for our application. It can be a website or mobile app. The user wants to authenticate with our application and goes to the login page.&lt;/p&gt;

&lt;p&gt;The application client will ask for the user's credentials, like email/username, and password. When the user enters the credentials, the following authentication flow will be initialized:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;application client&lt;/strong&gt; will take the credentials and send them to the &lt;strong&gt;authentication server&lt;/strong&gt; in the body of an HTTP Post request via a secure &lt;strong&gt;HTTPS&lt;/strong&gt; connection.&lt;/li&gt;
&lt;li&gt;The authentication server takes the credentials and checks if the user with the provided credentials exists. If the &lt;strong&gt;user is found&lt;/strong&gt;, the authentication server will &lt;strong&gt;generate a JWT&lt;/strong&gt; and return it as a response to the request.&lt;/li&gt;
&lt;li&gt;The application client now holds JWT specific to the user and can use it to access &lt;strong&gt;protected resources&lt;/strong&gt; on behalf of the user. It will now redirect the user to the main page of the application and make a new HTTP GET request &lt;strong&gt;with the token&lt;/strong&gt; provided via the HTTP Authorization header on the application server.&lt;/li&gt;
&lt;li&gt;The application server will take the token provided via the Authorization header and &lt;strong&gt;verify&lt;/strong&gt; its signature and claims. If the token is valid, the application server will return user-specific data to the application client.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It is very easy to split the authentication server from our application server when using JWT. This is why we can outsource the authentication part to third-party services like Clerk, Auth0, or any other provider. This allows us to focus on the business logic of our application, which is handled by the application server.&lt;/p&gt;

&lt;p&gt;Now that we understand how the authentication flow works, we will focus on the authentication server, which is responsible for &lt;strong&gt;generating JWT&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Our goal here is to point out important parts related to JWT generation and verification. We are &lt;strong&gt;not going&lt;/strong&gt; to write server or business logic implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication server &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;We already said that the authentication server is used to authenticate the user and generate JWT, which can be used by the application client to access restricted resources on the application server.&lt;/p&gt;

&lt;p&gt;Before handling the requests from the application client, we have to prepare all the necessary data required for token generation. The first thing we need to do is decide which algorithm to use for signing JWT signatures. Based on the listed benefits we saw before, I think it is safe to say that the &lt;strong&gt;RS256&lt;/strong&gt; algorithm would be a better option than the HS256 algorithm.&lt;/p&gt;

&lt;p&gt;I hope you still remember how RS256 works. Since it uses RSA encryption, we have to generate an RSA key pair: a private and public key. There are many ways to do this, but since we will work with Node, it is also fitting to generate RSA keys using Node.&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;crypto&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;KEYS_DIR_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./keys&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="nx"&gt;generateKeyPair&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;generateKeyPairSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rsa&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="na"&gt;modulusLength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2048&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;publicKeyEncoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spki&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;privateKeyEncoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pkcs8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pem&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;generateKeyPair&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;KEYS_DIR_PATH&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;KEYS_DIR_PATH&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./keys/private.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;privateKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./keys/public.pem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;publicKey&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simple script can be used to generate the required RSA keys. It uses Node's native &lt;code&gt;crypto&lt;/code&gt; module to generate the keys. When keys are generated, we just save them in the destination directory under the specified name. Private and public keys are saved in &lt;code&gt;keys/private.pem&lt;/code&gt; and &lt;code&gt;keys/public.pem&lt;/code&gt; files, respectively. With the groundwork done, we can switch to the more exciting topic of generating the JWT.&lt;/p&gt;

&lt;p&gt;In our example, the authentication server will receive an HTTP POST request with credentials provided in the request's body. The authentication server needs to extract the credentials (username and password) and query the database to check if the user with the provided credentials exists. At this point, the server has retrieved user data and roles, and we can already define JWT payloads using user data.&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;JWT_PAYLOAD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="cm"&gt;/**
   * Custom claims.
   * This can be anything, depending on the use-case you have.
   */&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;EDITOR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="cm"&gt;/**
   * Registered claims.
   */&lt;/span&gt;
  &lt;span class="na"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;22334455&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;iat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;iss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Authentication server (NO.1)&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have a &lt;code&gt;JWT_PAYLOAD&lt;/code&gt; that holds data related to the user. You can notice that we have provided a couple of registered claims; we have talked about them in previous sections. Probably the most important one is &lt;code&gt;exp&lt;/code&gt;, which says that the token will expire in &lt;strong&gt;3 days&lt;/strong&gt;. For &lt;code&gt;iat&lt;/code&gt; and &lt;code&gt;exp&lt;/code&gt;, we have to use the &lt;a href="https://en.wikipedia.org/wiki/Unix_time"&gt;Unix timestamp&lt;/a&gt; format.&lt;/p&gt;

&lt;p&gt;Other than registered claims, we also have a couple of custom claims. Here, we have the option to specify the claim name and claim value. Those claims are application-specific, and we can provide as much as we like. But be careful; those claims are visible to everyone, so they should &lt;strong&gt;not contain&lt;/strong&gt; sensitive data.&lt;/p&gt;

&lt;p&gt;With the payload ready, we need to prepare the header. We already know which algorithm to use, so the header for our token will look 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;JWT_HEADER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;alg&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;RS256&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;typ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JWT&lt;/span&gt;&lt;span class="dl"&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 next step is to create a JWT signature. For this part, we can use already-existing &lt;strong&gt;npm packages&lt;/strong&gt;. You might ask, Why use npm packages? The answer is quite simple. This algorithm is complex and hard to implement; it is much faster and more secure to rely on a well-tested package maintained by a lot of smart people.&lt;/p&gt;

&lt;p&gt;In this case, I decided to use the &lt;code&gt;jose&lt;/code&gt; npm package. It is well maintained, supports all JWT use-cases, and has a nice growing community of supporters. To use it, we first need to install the package by running the following command:&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;jose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This module provides a lot of useful functions and utilities, but we will focus only on a couple of them. You can &lt;a href="https://github.com/panva/jose"&gt;read more&lt;/a&gt; about the module itself if you feel like it.&lt;/p&gt;

&lt;p&gt;Before using any utilities provided by the module, we have to import the RSA private key. This key will be used for signing the signature hash.&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;PRIVATE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./keys/private.pem&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="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&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;runtimePrivateKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;jose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importPKCS8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JWT_HEADER&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;alg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just have to read the content of the &lt;code&gt;./keys/private.pem&lt;/code&gt; file and save it into &lt;code&gt;PRIVATE_KEY&lt;/code&gt; const. Before the &lt;code&gt;jose&lt;/code&gt; module can use it, we have to make a runtime-specific private key using the &lt;code&gt;importPKCS8&lt;/code&gt; function and save it into the &lt;code&gt;runtimePrivateKey&lt;/code&gt; const.&lt;/p&gt;

&lt;p&gt;When the runtime-specific private key is ready, we can generate the final token in its compact form using the &lt;code&gt;sign&lt;/code&gt; method on the instance of the &lt;code&gt;SignJWT&lt;/code&gt; class.&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;generatedToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;jose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;SignJWT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JWT_PAYLOAD&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setProtectedHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JWT_HEADER&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runtimePrivateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might think, What just happened? We did not encode the payload and header or take any intermediate steps, as described in previous sections. Well, simply put, the &lt;code&gt;jose&lt;/code&gt; module did it for us; in fact, all the following things are covered by the module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Convert the &lt;code&gt;JWT_PAYLOAD&lt;/code&gt; object into the stringified version and encode it using &lt;code&gt;base64url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Convert the &lt;code&gt;JWT_HEADER&lt;/code&gt; object into the stringified version and encode it using &lt;code&gt;base64url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Generate the signature using the encoded header, encoded payload, and RSA private key.&lt;/li&gt;
&lt;li&gt;Encode the JWT signature using &lt;code&gt;base64url&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Concatenate the encoded header, encoded payload, and encoded signature with a &lt;code&gt;.&lt;/code&gt; period and produce a compact form of the token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope you can see value in using the &lt;code&gt;jose&lt;/code&gt; module here. It took care of all things related to token generation. At the end, we got the final token just by using a simple API. If we log the value of &lt;code&gt;generatedToken&lt;/code&gt;, it looks 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="c1"&gt;// Separated with a new line for an easier overview&lt;/span&gt;
&lt;span class="nx"&gt;eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;eyJuYW1lIjoiSm9obiBEb2UiLCJyb2xlIjoiRURJVE9SIiwic3ViIjoiMjIzMzQ0NTUiLCJpYXQiOjE2ODk0MDcxMDYsImV4cCI6MTY4OTY2NjMwNiwiaXNzIjoiQXV0aGVudGljYXRpb24gc2VydmVyIChOTy4xKSJ9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;v9LXLIjGPtakpRvGPYYDvPyyQ1avxmJW2zlJ4ND_74YIPbloZBPGtJ3gMCjY40m5Qbf1jy7xv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;jIphLOi2EBYNW4EUIGqZb3Lj0Tn4W_hZiL9tq1ASUma4nURVPREeDGpD_B5AojIjk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;iiLc_K3Iin8kwG3u5L3RDU9zLOEdW2TUPwR&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Q4NNm8kG_9OBoA2z0H6Uknk4Udv6VL0EuKKds1OXgsHAK9vRi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;psGISB0W1AGHjegPFJXotcXW2DOBHKAUm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;NTwcpPt0YMzNLmTLpfwzsqYyHJxwneQW&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;KQOTpBNpIUuWVh3qyJumyVk10hHLMlr8lOeHL_KjmH1vupOVA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the authentication server can return the token to the application client as a response to the initial request. The application client can use the token to request protected data from the application server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Application server &lt;a&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;It's time to focus on the application server. This is where we need to handle token verification. Again, let's start with what we already know. First of all, we need access to the public key, and we also know that the algorithm used to sign the token was RS256.&lt;/p&gt;

&lt;p&gt;As a side node, we could have gotten the information about the algorithm used from the header itself, as it is visible the same as the payload.&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;PUBLIC_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./keys/public.pem&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="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&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;SIGNATURE_ALGORITHM&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;RS256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We just took those values and saved them into the &lt;code&gt;PUBLIC_KEY&lt;/code&gt; and &lt;code&gt;SIGNATURE_ALGORITHM&lt;/code&gt; const. You need to make sure that the public key is correlated, part of the same RSA key pair, to the private key used to sign the token.&lt;/p&gt;

&lt;p&gt;The application client will make an HTTP GET request to one of the endpoints on our application server. This request will also include the token provided via the HTTP Authorization header.&lt;/p&gt;

&lt;p&gt;The application server has to extract the token from the Authorization header so it can be verified. The token received from the header might look 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="c1"&gt;// Separated with a new line for an easier overview&lt;/span&gt;
&lt;span class="nx"&gt;eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;eyJuYW1lIjoiSm9obiBEb2UiLCJyb2xlIjoiRURJVE9SIiwic3ViIjoiMjIzMzQ0NTUiLCJpYXQiOjE2ODk0MDcxMDYsImV4cCI6MTY4OTY2NjMwNiwiaXNzIjoiQXV0aGVudGljYXRpb24gc2VydmVyIChOTy4xKSJ9&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nx"&gt;v9LXLIjGPtakpRvGPYYDvPyyQ1avxmJW2zlJ4ND_74YIPbloZBPGtJ3gMCjY40m5Qbf1jy7xv&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;jIphLOi2EBYNW4EUIGqZb3Lj0Tn4W_hZiL9tq1ASUma4nURVPREeDGpD_B5AojIjk&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;iiLc_K3Iin8kwG3u5L3RDU9zLOEdW2TUPwR&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;Q4NNm8kG_9OBoA2z0H6Uknk4Udv6VL0EuKKds1OXgsHAK9vRi&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;psGISB0W1AGHjegPFJXotcXW2DOBHKAUm&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;NTwcpPt0YMzNLmTLpfwzsqYyHJxwneQW&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;KQOTpBNpIUuWVh3qyJumyVk10hHLMlr8lOeHL_KjmH1vupOVA&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is the same token that we generated previously. When the token is extracted, it has to be verified to confirm that the user is legit. Again, we will use the &lt;code&gt;jose&lt;/code&gt; module to help us with this process.&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;runtimePublicKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;jose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;importSPKI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;PUBLIC_KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;SIGNATURE_ALGORITHM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;try&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;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;protectedHeader&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;jose&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;jwtVerify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;userToken&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;runtimePublicKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;algorithms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;SIGNATURE_ALGORITHM&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;issuer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication server (NO.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;requiredClaims&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;iss&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="s1"&gt;exp&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="s1"&gt;role&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;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&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;TokenExpiredError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Token has expired&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;TokenExpiredError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ERR_TOKEN_EXPIRED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;TokenExpiredError&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Token verified &amp;amp; User authenticated&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Verification failed &amp;amp; Access denied&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, we have to import the public key and convert it to the runtime-specific key representation required by the module. We can do that using the &lt;code&gt;importSPKI&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;We then use the &lt;code&gt;jwtVerify&lt;/code&gt; function, providing the token, public key, and additional options. Via the options object, we can fine-tune verification with some smart defaults. Here is what we provided:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;algorithms&lt;/code&gt; - specifies all allowed algorithms.
Our tokens will be signed with the &lt;code&gt;RS256&lt;/code&gt; algorithm, meaning only this algorithm has to be allowed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;issuer&lt;/code&gt; - specifies allowed issuers.
In authentication server, we set issuer to &lt;code&gt;Authentication server (NO.1)&lt;/code&gt; which means that all tokens, generated by the authentication server, must have this issuer set.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;requiredClaims&lt;/code&gt; - defines which claims must be available in the payload.
We could list all the claims that the authentication server would use, but we have listed only important ones.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At the end, this function will return the payload and header, both in the form of JavaScript object. If any of these requirements are not met, the &lt;code&gt;jwtVerify&lt;/code&gt; function will throw an error indicating that verification was not successful. Here is what the &lt;code&gt;jwtVerify&lt;/code&gt; function did for us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take the token and extract the encoded header, payload, and signature.&lt;/li&gt;
&lt;li&gt;Decode and convert the header and payload to plain JavaScript objects.&lt;/li&gt;
&lt;li&gt;Check which algorithm is used to sign the token, and throw an error if it is not &lt;code&gt;RS256&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check that the issuer claim is set in the payload and allow only &lt;code&gt;Authentication servers (NO.1)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check the required claims provided in the payload and throw an error if a required claim is missing.&lt;/li&gt;
&lt;li&gt;Verify the token signature using the RS256 algorithm.&lt;/li&gt;
&lt;li&gt;Return the payload and header as a result.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is obvious that &lt;code&gt;jose&lt;/code&gt; module does a lot of heavy lifting for us, and this is why we want to use it anyway. Without the &lt;code&gt;jose&lt;/code&gt; module, we would have to implement all these things, done by the module, manually.&lt;/p&gt;

&lt;p&gt;Next, in the code above, we check the expiration time provided via &lt;code&gt;exp&lt;/code&gt; claim. We just need to compare the &lt;code&gt;exp&lt;/code&gt; claim with the current time on the server. If the timestamp provided in the &lt;code&gt;exp&lt;/code&gt; claim is less than the current time, the token has expired, and we throw another verification error.&lt;/p&gt;

&lt;p&gt;If no error has occurred during the verification process, we can conclude that the token is valid and can be trusted. Application servers can now return protected data requested by the application client.&lt;/p&gt;

&lt;h2&gt;
  
  
  JWT and Authorization &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;We've said a lot of times that JWT can also be used for authorization. But what is this authorization, and how is it different from authentication?&lt;/p&gt;

&lt;p&gt;In simple terms, authorization is the process of determining whether an entity has the necessary rights and permissions to access a particular resource. It is basically &lt;em&gt;access control&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Authorization usually only kicks in after authentication, which verifies identity. Once a user is authenticated, authorization comes into play to determine what they are allowed to do or access. It usually involves using some kinds of roles and/or permissions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gJz7Js1e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pc1w648g5u0fijvbr1c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gJz7Js1e--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4pc1w648g5u0fijvbr1c.png" alt="JWT and authorization" width="800" height="258"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case, the user is already authenticated. We know his name is &lt;em&gt;John Doe&lt;/em&gt;, and we know he has the role of &lt;em&gt;editor&lt;/em&gt;. However, this user should not have access to all available APIs.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;First verify, and then handle authorization logic.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the user asks the application client to &lt;strong&gt;create&lt;/strong&gt; a new post using the &lt;code&gt;/create&lt;/code&gt; REST API endpoint, the server returns an HTTP Response with the status &lt;strong&gt;200 OK&lt;/strong&gt;. This means that this request has been successfully fulfilled.&lt;/p&gt;

&lt;p&gt;On the other hand, when users try to &lt;strong&gt;delete&lt;/strong&gt; a post using the &lt;code&gt;/delete&lt;/code&gt; REST API endpoint, the server returns an HTTP Response with the status &lt;strong&gt;403 Forbidden&lt;/strong&gt;. This means that the user does not have the required permissions to access this API.&lt;/p&gt;

&lt;p&gt;This example provides a simple use case for authorization. Depending on the permissions that the user has, different resources can be accessed.&lt;/p&gt;

&lt;p&gt;We can easily extend the application server from our previous example to implement this behavior. Remember, we already have a custom &lt;code&gt;role&lt;/code&gt; claim in the payload.&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;// JWT payload&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;EDITOR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;22334455&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;iat&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1689407106&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1689666306&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;iss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication server (NO.1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can just use this &lt;code&gt;role&lt;/code&gt; claim to implement simple access control. As you might have noticed, authorization logic will be implemented on the application server since this server handles the business login.&lt;/p&gt;

&lt;p&gt;In case JWT does not have any claims to resolve permission level, like &lt;code&gt;role&lt;/code&gt;, we would also have to modify the authentication server to generate tokens with the required claim.&lt;/p&gt;

&lt;p&gt;Our application server now has two additional endpoints: &lt;code&gt;/create&lt;/code&gt; and &lt;code&gt;/delete&lt;/code&gt;. When a user makes a request to one of those endpoints, the application server needs to verify the token in exactly the same way as before.&lt;/p&gt;

&lt;p&gt;We just have to extend the &lt;code&gt;/delete&lt;/code&gt; API handler to make sure that user has one of the allowed roles. It is as simple as adding an &lt;code&gt;if&lt;/code&gt; statement.&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;ALLOWED_ROLES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ADMIN&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="s1"&gt;CHIEF_EDITOR&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;ALLOWED_ROLES&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Can access (Response OK 200)&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;// Can not access (Response 403 Forbidden)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this simple check, we have added authorization to the &lt;code&gt;/delete&lt;/code&gt; endpoint. As our user has the role of &lt;code&gt;EDITOR&lt;/code&gt;, he would not be able to access this API.&lt;/p&gt;

&lt;p&gt;This is just a simple example to demonstrate how easy it can be to add simple authorization using JWT. Because of JWT's flexibility, we can add any claims to the token to fine-tune access control even further.&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practices &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Over the years of usage by a lot of developers and companies, several recommendations and workflows have emerged that are so common and essential that they are rightfully described as &lt;strong&gt;best practices&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;All though "best practices" are good things to follow and try to implement in our own applications, there are so many of them that it is often not possible. I will mention some of the most important ones, in my opinion, but I encourage you to investigate this segment on your own.&lt;/p&gt;

&lt;p&gt;Always &lt;strong&gt;use HTTPS&lt;/strong&gt; when transmitting JWT. It might seem obvious, but there are many websites out there that do not use HTTPS. Remember, JWT is often used as an access token, and it is critical to protect it from network attacks and other security threats.&lt;/p&gt;

&lt;p&gt;JWT is flexible enough to allow us to put any kind of claim into the payload. But whatever you do with the token, &lt;strong&gt;do not expose sensitive data&lt;/strong&gt; in the payload. If you use a signed token (JWS), everyone can see what's in the payload. The information provided in the payload is not secure at all.&lt;/p&gt;

&lt;p&gt;When possible, &lt;strong&gt;use asymmetric algorithms&lt;/strong&gt;. We already talked about the benefits of asymmetric algorithms over symmetric ones when we compared RS256 and HS256. Always try to use asymmetric algorithms, as they provide much more security.&lt;/p&gt;

&lt;p&gt;To improve security, &lt;strong&gt;always set &lt;code&gt;ext&lt;/code&gt; claim&lt;/strong&gt; to a reasonably &lt;strong&gt;short expiration time&lt;/strong&gt;. Short-lived tokens reduce the window of vulnerability if a token is stolen or compromised. Short-lived tokens can be used in combination with refresh tokens to renew access without requiring re-authentication.&lt;/p&gt;

&lt;p&gt;Make sure that the token is issued by someone you know, so &lt;strong&gt;always check for the &lt;code&gt;iss&lt;/code&gt; claim&lt;/strong&gt;. Every token should have this claim, and there is no reason for a token not to include it. Tokens without an &lt;code&gt;iss&lt;/code&gt; claim should just be rejected.&lt;/p&gt;

&lt;p&gt;This one is obvious, but &lt;strong&gt;always verify and validate incoming JWTs&lt;/strong&gt;. Verify the signature to ensure the token's authenticity and integrity. Validate the token's claims to avoid accepting expired, not properly formatted, or tampered tokens.&lt;/p&gt;

&lt;p&gt;Consider implementing &lt;strong&gt;token revocation&lt;/strong&gt; mechanisms, such as blacklisting, to handle scenarios where tokens are compromised.&lt;/p&gt;

&lt;p&gt;On client applications, tokens have to be stored somewhere. Most often than not, they are stored in the local storage of the client's browser. Make sure to &lt;strong&gt;protect token storage on the client side&lt;/strong&gt; from common attacks like, for example, cross-site scripting (XSS) attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Include the &lt;code&gt;aud&lt;/code&gt; claim&lt;/strong&gt; to specify the intended audience of the token. This helps ensure the token is used for its intended purpose. The application server should check for the &lt;code&gt;aud&lt;/code&gt; claim and verify that the token was issued to an audience that the server is part of.&lt;/p&gt;

&lt;p&gt;Always remember that the security of JWT depends mostly on how we use and verify it. There is no magic algorithm that can save us if the underlying use of JWT is flawed. Following best practices is a way to prevent flawed use of JWT. They help us ensure the secure and effective use of JWT in our applications while mitigating potential security risks and vulnerabilities.&lt;/p&gt;

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

&lt;p&gt;This was probably a long read, and you have finally reached the end. I hope you have more theoretical as well as practical knowledge about JWT (JSON Web Token).&lt;/p&gt;

&lt;p&gt;As an open standard that provides a secure way to transmit information between parties in a compact and self-contained way, JWT has emerged as a powerful and versatile tool for secure authentication and authorization in &lt;em&gt;modern&lt;/em&gt; applications.&lt;/p&gt;

&lt;p&gt;Understanding how JWT works is essential for its proper implementation. As applications and networks continue to &lt;em&gt;evolve&lt;/em&gt;, so will security standards. What is good today does not mean it will be good tomorrow. We always have to be ready to act and not fall behind in this &lt;em&gt;evolution&lt;/em&gt;. I will try to keep this article up-to-date in case there are any changes in the JWT world.&lt;/p&gt;

&lt;p&gt;Through this comprehensive guide, I really hope you have gained the knowledge and insights needed to finally say, "Yes, I understand JWT".&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://wannabedev.io/"&gt;wannabedev.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>jwt</category>
      <category>security</category>
      <category>guide</category>
    </item>
    <item>
      <title>Create text change hover effect with JavaScript</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Tue, 21 Mar 2023 18:25:30 +0000</pubDate>
      <link>https://dev.to/rmmgc/create-text-change-hover-effect-with-javascript-4k5g</link>
      <guid>https://dev.to/rmmgc/create-text-change-hover-effect-with-javascript-4k5g</guid>
      <description>&lt;p&gt;I stumbled upon one website that had this hover effect where the original text would change to some random characters and start revealing itself over time.&lt;/p&gt;

&lt;p&gt;It looked like a fun exercise, so I decided to recreate it. Below you can see how it looks and check out the source code as well. This is a beginner-friendly article and includes a step-by-step guide. If you completely understand the source code, feel free to skip reading so you do not waste your time.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/web-platform-99k2qs?file=index.html&amp;amp;view=preview" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In case you decided to continue reading, you might be interested in what we are going to cover here. We will start with a basic HTML structure and mention some CSS styles. However, the main focus will be on JavaScript. You can learn how to listen for and handle events, a little bit of string manipulation, and how to leverage the power of closure. If you are ready, let's get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  HTML structure
&lt;/h2&gt;

&lt;p&gt;As for any hover effect, you need to have something that you want to hover over. In this case, let's create a couple of links using &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag and put them into a &lt;code&gt;body&lt;/code&gt; tag, just for demonstration purposes.&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;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-hover-effect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;pricing&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-hover-effect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;projects&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-hover-effect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;about us&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;a&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-hover-effect"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;subscribe!&lt;span class="nt"&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that every &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag has a &lt;code&gt;class&lt;/code&gt; attribute with a value of &lt;code&gt;text-hover-effect&lt;/code&gt;. We will need it later so we can target those HTML elements with JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS styles
&lt;/h2&gt;

&lt;p&gt;Since the HTML structure is ready, let's add some styles. In this case, I only want to do some simple things, like changing the background color and making sure that links are centered on the page. We can also add styles to links so they look a bit nicer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;box-sizing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;border-box&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;body&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="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#18122b&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;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;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;flex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&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;100vh&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;sans-serif&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#635985&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;uppercase&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;letter-spacing&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.1rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2.6rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;font-weight&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bold&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;box-shadow&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;0&lt;/span&gt; &lt;span class="m"&gt;2rem&lt;/span&gt; &lt;span class="m"&gt;1rem&lt;/span&gt; &lt;span class="n"&gt;rgba&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="m"&gt;0&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="m"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&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.6rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border-radius&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.4rem&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;370px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#635985&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;text-decoration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&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="nb"&gt;block&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;margin-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2rem&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;I will not go into details about what every CSS declaration does, you can always play around with them in the sample project. However, I want to bring your attention to one thing.&lt;/p&gt;

&lt;p&gt;Even though we added some CSS, it is actually not required. Notice that there is not even a &lt;code&gt;:hover&lt;/code&gt; pseudo-class. This is because the hover effect will be handled entirely by JavaScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the effect
&lt;/h2&gt;

&lt;p&gt;To implement the desired effect and behavior, we first need to understand it. Take a look at the following image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W7yqVNCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oen1q97q44svv2g8ctgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W7yqVNCK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/oen1q97q44svv2g8ctgv.png" alt="Illustration of required actions to reproduce the hover effect" width="394" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the default state, the original text is visible. When the cursor hovers over the text, it will immediately be populated with random characters. Only the first character from the original text should remain the same.&lt;/p&gt;

&lt;p&gt;After some artificial delay, the character in the second position from the original text will replace the randomly generated character in the same position. This delay and replace process will continue until the last character is reached and the original text is completely revealed.&lt;/p&gt;

&lt;p&gt;I hope this was clear enough for you to understand what we are trying to create here. If not, do not worry; we will split it into manageable chunks and cover every chunk separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript code
&lt;/h2&gt;

&lt;p&gt;This is the part where we will spend the most time. First of all, we need to somehow generate random characters for our effect. We can do that by creating a simple array of characters.&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;// 🔡 Characters to cycle trough&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;allowedCharacters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X&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="s1"&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="s1"&gt;Y&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="s1"&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="s1"&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="s1"&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="s1"&gt;0&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="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The variable &lt;code&gt;allowedCharacters&lt;/code&gt; holds a list of the allowed characters. Feel free to add or remove them from your version.&lt;/p&gt;

&lt;p&gt;We also need a function that can randomly select one of the characters from the previously created list.&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;// 🎁 Function to return random character&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getRandomCharacter&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;randomIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;allowedCharacters&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;allowedCharacters&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;randomIndex&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;Function &lt;code&gt;getRandomCharacter&lt;/code&gt; uses &lt;code&gt;Math&lt;/code&gt; object to &lt;em&gt;randomly&lt;/em&gt; generate a number, index, between &lt;code&gt;0&lt;/code&gt; and the &lt;code&gt;length&lt;/code&gt; of the &lt;code&gt;allowedCharacters&lt;/code&gt; array. The generated index is then used to get the character from the &lt;code&gt;allowedCharacters&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To handle hover events, we need to get all &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags and attach event listeners to all of them.&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;// 🛠 Event handler&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleHoverEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// TODO: Add implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Attach an event listener to elements&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;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.text-hover-effect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&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;element&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;mouseover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleHoverEvent&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;Here, &lt;code&gt;document.querySelectorAll&lt;/code&gt; is used to get all elements that have a value of &lt;code&gt;text-hover-effect&lt;/code&gt; in the &lt;code&gt;class&lt;/code&gt; attribute. Since we only added this class to &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags, it will return the iterable collection of Anchor, &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, elements.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;addEventListener&lt;/code&gt;, we can add &lt;code&gt;mouseover&lt;/code&gt; event listener to every element and pass the function &lt;code&gt;handleHoverEvent&lt;/code&gt; to handle the events. Now, whenever a user hovers over any of &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tags, &lt;code&gt;handleHoverEvent&lt;/code&gt; function will be executed.&lt;/p&gt;

&lt;p&gt;So far, so good. The groundwork is complete; it's time to work on the hover effect implementation now. As we already said, we will split the task into multiple chunks. For the beginning, let's focus on the following part:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Q27raKsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2dubtbn73o2on3ze5je.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Q27raKsv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u2dubtbn73o2on3ze5je.png" alt="First step of the hover effect" width="319" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On hover, we have to replace the original text, except for the first character, with a randomly generated one.&lt;/p&gt;

&lt;p&gt;When an event is triggered, the &lt;code&gt;handleHoverEvent&lt;/code&gt; function gets called and an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Event"&gt;Event&lt;/a&gt;-based object will be passed as an argument to the function.&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;function&lt;/span&gt; &lt;span class="nx"&gt;handleHoverEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&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;randomizedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&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="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRandomCharacter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&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="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}${&lt;/span&gt;&lt;span class="nx"&gt;randomizedText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="s2"&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;The function will receive the &lt;code&gt;e&lt;/code&gt;, the event object, when the event is triggered. First, we have to save the current text value from the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag that was hovered. To do so, we can use &lt;code&gt;e.target.innerHTML&lt;/code&gt; and save the value into the &lt;code&gt;text&lt;/code&gt; variable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep in mind that &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML"&gt;innerHTML&lt;/a&gt; gets or sets the HTML markup contained within the element. If your hovered element has other HTML tags as children, they will be serialized and returned as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Next, we need to generate randomized text with the same length as the original. This is where we can use the &lt;code&gt;getRandomCharacter&lt;/code&gt; function that was created before.&lt;/p&gt;

&lt;p&gt;The value saved in the &lt;code&gt;text&lt;/code&gt; variable is a string that includes multiple characters. But &lt;code&gt;getRandomCharacter&lt;/code&gt; generates only one character per call. To solve this problem, we can convert the original text into an array of characters using the &lt;code&gt;split('')&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Now that we have an array, we can chain the &lt;code&gt;map&lt;/code&gt; method and pass the &lt;code&gt;getRandomCharacter&lt;/code&gt; function to it. Now, for every original character, a random one will be generated. Finally, to convert the resulting array back to a string, the &lt;code&gt;join('')&lt;/code&gt; method is used.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--pw7zMxSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/986jkzoto8x8b8308pq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pw7zMxSz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/986jkzoto8x8b8308pq3.png" alt="Generate random characters from the original text" width="251" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;"subscribe"&lt;/code&gt; string is used as an example to illustrate how the text is being processed. You can see that at the end, we have randomly generated text that is the same length as the original one.&lt;/p&gt;

&lt;p&gt;Good, we now have two strings, one original and one randomly generated. The last step is to combine them and update the &lt;code&gt;e.target.innerHTML&lt;/code&gt; property. To get the first character from the original text, we can use &lt;code&gt;text.substring(0,1)&lt;/code&gt; and to get the rest of the characters from the randomized text, we can use &lt;code&gt;randomizedText.substring(1)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qprcJ1LG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eja2wmymr8nh3qipb2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qprcJ1LG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2eja2wmymr8nh3qipb2p.png" alt="Combine substrings into the final string" width="409" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We could have done this in a different way as well, but I think using the &lt;code&gt;substring&lt;/code&gt; method is totally fine, and, if interested, you can find more &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/substring"&gt;details here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After some delay, the next character from the original text must be shown instead of the random one, and it needs to be repeated until the last character is revealed. We can achieve this using &lt;code&gt;for&lt;/code&gt; loop and the &lt;code&gt;setTimeout&lt;/code&gt; web API method.&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;function&lt;/span&gt; &lt;span class="nx"&gt;handleHoverEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&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;randomizedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&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="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRandomCharacter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&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="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;text&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="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;=&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;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="nx"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;)}${&lt;/span&gt;&lt;span class="nx"&gt;randomizedText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&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="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="mi"&gt;70&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;String values are iterable, so we can use the &lt;code&gt;for&lt;/code&gt; loop on them as well. We will loop through the original text saved in the &lt;code&gt;text&lt;/code&gt; variable. In every iteration, we invoke the &lt;code&gt;setTimeout&lt;/code&gt; function. Notice that the delay for &lt;code&gt;setTimeout&lt;/code&gt; is multiplied by the &lt;code&gt;i&lt;/code&gt; value. This allows us to properly schedule updates, one after another, using the same wait time of &lt;code&gt;70&lt;/code&gt; milliseconds between each update.&lt;/p&gt;

&lt;p&gt;Lastly, we just needed to modify the assignment part of &lt;code&gt;e.target.innerHTML&lt;/code&gt; to include &lt;code&gt;nextIndex&lt;/code&gt; value instead of hardcoded ones. We need the &lt;code&gt;nextIndex&lt;/code&gt; to ensure that &lt;code&gt;substring&lt;/code&gt; method works properly and produces the expected result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gXiPCeER--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cczb9gffynithx17vjrz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gXiPCeER--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cczb9gffynithx17vjrz.png" alt="Illustration of scheduled tasks" width="164" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We used the &lt;code&gt;for&lt;/code&gt; loop and &lt;code&gt;setTimeout&lt;/code&gt; to create scheduled tasks. When the delay time expires, &lt;code&gt;setTimeout&lt;/code&gt; will invoke the task function, which will update the &lt;code&gt;innerHTML&lt;/code&gt; value of the hovered element. This will be repeated for every scheduled task, generated by the &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;

&lt;p&gt;Our effect should work fine now, but there is one more problem. If you hover over the element really fast, the &lt;code&gt;handleHoverEvent&lt;/code&gt; function could be triggered multiple times. This is obviously not what we want. We need to make sure that &lt;code&gt;handleHoverEvent&lt;/code&gt; cannot be triggered unless the currently running effect is over.&lt;/p&gt;

&lt;p&gt;To make this happen, we can rely on the power of closure. Consider the following code:&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;// 🏭 Creates new event handler with a private variable&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;createEventHandler&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// 🏃‍♂️ Private variable: Keep track of the event in progress&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// 👇 Event handler implementation&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleHoverEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&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;isInProgress&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="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;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&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;randomizedText&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&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="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getRandomCharacter&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&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="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;text&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="nx"&gt;isInProgress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;=&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;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="nx"&gt;nextIndex&lt;/span&gt;&lt;span class="p"&gt;)}${&lt;/span&gt;&lt;span class="nx"&gt;randomizedText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextIndex&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;text&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="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;isInProgress&lt;/span&gt; &lt;span class="o"&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;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="mi"&gt;70&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;Most of the code is the same, but there are a couple of important differences. First of all, we have put our &lt;code&gt;handleHoverEvent&lt;/code&gt; function inside another function called &lt;code&gt;createEventHandler&lt;/code&gt;. Also, we make sure that &lt;code&gt;createEventHandler&lt;/code&gt; returns &lt;code&gt;handleHoverEvent&lt;/code&gt;. In doing so, we have created the conditions for closure to occur.&lt;/p&gt;

&lt;p&gt;Why do we even need closure in the first place? In this particular case, we need to create a variable where we can store information if the effect is in progress. This variable must be private to the &lt;code&gt;handleHoverEvent&lt;/code&gt; function since only this function should be able to update it. When it comes to creating private variables, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures"&gt;closure&lt;/a&gt; is the way to go. &lt;/p&gt;

&lt;p&gt;In &lt;code&gt;createEventHandler&lt;/code&gt;, we have defined the variable &lt;code&gt;isInProgress&lt;/code&gt; and initialized it with &lt;code&gt;false&lt;/code&gt;. This variable is used to keep track of whether the current effect is still in progress.&lt;/p&gt;

&lt;p&gt;In the function &lt;code&gt;handleHoverEvent&lt;/code&gt;, as soon as the loop starts, we will set &lt;code&gt;isInProgress&lt;/code&gt; to &lt;code&gt;true&lt;/code&gt;, indicating that the effect has started. When the last task is executed, &lt;code&gt;isInProgress&lt;/code&gt; is set to &lt;code&gt;false&lt;/code&gt;, indicating that the effect has finished.&lt;/p&gt;

&lt;p&gt;In the same function, at the beginning, we will check if &lt;code&gt;isInProgress&lt;/code&gt; is set to &lt;code&gt;true&lt;/code&gt;. In case it's set, we can assume that the effect is still running and &lt;code&gt;return&lt;/code&gt; immediately, effectively skipping the handling of the event.&lt;/p&gt;

&lt;p&gt;Now we need to modify the code responsible for attaching an event handler to the &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; tag, Anchor elements.&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="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.text-hover-effect&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;element&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;eventHandler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createEventHandler&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;element&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;mouseover&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;eventHandler&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;For every Anchor, &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt;, element new &lt;code&gt;handleHoverEvent&lt;/code&gt; function will be created using the &lt;code&gt;createEventHandler&lt;/code&gt; function. The resulting function is then saved into the &lt;code&gt;eventHandler&lt;/code&gt; and passed to the &lt;code&gt;addEventListener&lt;/code&gt;. Since we have leveraged the power of closure to keep track of the event in progress, new events will not be handled until the currently running one is finished.&lt;/p&gt;

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

&lt;p&gt;Initially, I did not plan to make this tutorial too big, but it turned out to be quite lengthy.&lt;/p&gt;

&lt;p&gt;I wanted to give a detailed explanation of how this hover effect could be achieved and to show that it is not difficult at all if you split it into smaller pieces. You should be able to do this for every task—split and conquer.&lt;/p&gt;

&lt;p&gt;This was also a nice opportunity to show just how useful the concept of closure is in JavaScript and how it can be leveraged in a practical example.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://ramomujagic.com/blog/"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Mastering the Mysteries of JavaScript Scopes</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Wed, 22 Feb 2023 07:28:41 +0000</pubDate>
      <link>https://dev.to/rmmgc/mastering-the-mysteries-of-javascript-scopes-2b3n</link>
      <guid>https://dev.to/rmmgc/mastering-the-mysteries-of-javascript-scopes-2b3n</guid>
      <description>&lt;p&gt;While writing your programs in JavaScript you will quickly get familiar with creating variables and functions, assigning values, using and updating them. But, have you ever asked yourself how the JavaScript knows which variable or function is accessible by the given statement, or how are these things managed internally?&lt;/p&gt;

&lt;p&gt;This is where &lt;em&gt;scopes&lt;/em&gt; and the &lt;em&gt;scope chain&lt;/em&gt; come into play. The concept of scopes and scope chain plays a vital role in determining the accessibility of variables and functions. Mastering their intricacies can make the difference between writing clean, maintainable code and struggling with bugs and unexpected behavior.&lt;/p&gt;

&lt;p&gt;In this article, we will dive deeper into the inner workings of scopes and explore how they impact your code. That being said, this is not an article for total beginners and basic understanding of JavaScript is required.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;
Lexical Scope

&lt;ul&gt;
&lt;li&gt;Global Scope&lt;/li&gt;
&lt;li&gt;Function Scope&lt;/li&gt;
&lt;li&gt;Block Scope&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Nested Scope&lt;/li&gt;
&lt;li&gt;
Scope Chain

&lt;ul&gt;
&lt;li&gt;Lookup&lt;/li&gt;
&lt;li&gt;Peek under the hood&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Lexical Scope
&lt;/h2&gt;

&lt;p&gt;From the perspective of a program, it is very important where you place variable or function declarations, as well as how and when you are using them.&lt;/p&gt;

&lt;p&gt;The reason it's important is because of &lt;em&gt;lexical scope&lt;/em&gt; and how the program behaves in relation to it. By definition, lexical scope determines the visibility and accessibility of variables and functions based on their position in the source code. It makes code easier to reason about and helps avoid naming conflicts between variables.&lt;/p&gt;

&lt;p&gt;In general, JavaScript has different kinds of scopes: &lt;strong&gt;global scope&lt;/strong&gt;, &lt;strong&gt;function scope&lt;/strong&gt; and, more recently, &lt;strong&gt;block scope&lt;/strong&gt;. Some might argue that there is also &lt;em&gt;module scope&lt;/em&gt;, but we will not discuss it in this article.&lt;/p&gt;

&lt;p&gt;You might have also heard about the term &lt;strong&gt;local scope&lt;/strong&gt;. It is a more general term that can refer to both function scope and block scope, depending on the context.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global Scope
&lt;/h3&gt;

&lt;p&gt;Let's immediately start with an example. Consider the following code.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;District 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;releaseYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2009&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&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="s2"&gt;Sci-Fi&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="s2"&gt;Thriller&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;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transformers: Age of Extinction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;releaseYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2014&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&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="s2"&gt;Adventure&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="s2"&gt;Sci-Fi&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;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is easy to spot that the &lt;code&gt;movies&lt;/code&gt; variable is declared, initialized and printed to console using &lt;code&gt;console.log&lt;/code&gt;. This is, however, not what I want to point out.&lt;/p&gt;

&lt;p&gt;Even now, with a program as simple as this, there is a scope created. This scope is referred to as &lt;strong&gt;global scope&lt;/strong&gt;. It exists in &lt;strong&gt;every program&lt;/strong&gt; and contains all other scopes that we could possibly define.&lt;/p&gt;

&lt;p&gt;Think of it as a container where variables and functions can be declared and other scopes created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XFxrScre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3pdlzfespcpgoayipgv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XFxrScre--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e3pdlzfespcpgoayipgv.png" alt="Global scope container" width="314" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When a variable or function is defined in global scope, it can be accessed from any other scope through the program. There are some exceptions to this, but it should not bother you for now.&lt;/p&gt;

&lt;p&gt;There is also one more important aspect of global scope, in JavaScript, called &lt;strong&gt;global object&lt;/strong&gt;. Global object &lt;strong&gt;always exists&lt;/strong&gt; in the global scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ksaULK3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n496a99iszl2vf4bessq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ksaULK3v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n496a99iszl2vf4bessq.png" alt="Global object shown inside the global scope" width="314" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We all know that JavaScript code can be executed in the browser. However, there are different environments that can run JavaScript code like, for example, Node.js runtime.&lt;/p&gt;

&lt;p&gt;Depending on the environment where JavaScript is hosted, a different global object might be present. In browsers, the global object is more commonly known as &lt;code&gt;Window&lt;/code&gt;, but in Node.js it's referred to as &lt;code&gt;global&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since the global object is part of JavaScript language, in ES2020 specification, it has finally received a unique identifier &lt;code&gt;globalThis&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function Scope
&lt;/h3&gt;

&lt;p&gt;Whenever you create a function, &lt;strong&gt;function scope&lt;/strong&gt; is created along with it. No matter if you use function definition, function expression or even arrow function, function scope is always present.&lt;/p&gt;

&lt;p&gt;It exists inside the function body. Every variable, or even other functions, created inside the body will be part of the function scope.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&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;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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;Look at the body of the function &lt;code&gt;printTitle&lt;/code&gt;, space between &lt;code&gt;{...}&lt;/code&gt;, it has two variables defined as &lt;code&gt;movie&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt;. Since variables are defined inside the function body, they are also part of the function scope.&lt;/p&gt;

&lt;p&gt;Also, notice that the &lt;code&gt;movies&lt;/code&gt; variable is referenced, but it's not defined in the function scope. This variable can still be used by the function, since it's created in the global scope. Remember, every variable created in the global scope is accessible in all other scopes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yFcocEoH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ze6i0055l1k74ooqfd7e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yFcocEoH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ze6i0055l1k74ooqfd7e.png" alt="Function scope inside the global scope" width="314" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see how function scope is created inside the global scope when function is defined. In the image, the global object is removed since we will not talk about it anymore, but keep in mind, it is always there in the global scope.&lt;/p&gt;

&lt;p&gt;You might have noticed that the identifier &lt;code&gt;index&lt;/code&gt; is marked with a blue color. When we defined the function &lt;code&gt;printTitle&lt;/code&gt;, we did it in the following way &lt;code&gt;function printTitle(index) {...}&lt;/code&gt;. In other words, it has one parameter called &lt;code&gt;index&lt;/code&gt; and, by default, every function parameter is added to the function scope.&lt;/p&gt;

&lt;p&gt;If you try to access &lt;code&gt;index&lt;/code&gt;, &lt;code&gt;movie&lt;/code&gt; or &lt;code&gt;title&lt;/code&gt; outside function scope, an error will be thrown.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&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;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;

  &lt;span class="c1"&gt;// 🖨 Prints to the console&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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="c1"&gt;// 🚫 ReferenceError: movie is not defined&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Variables defined in function scope can not be accessed outside the function. When referencing a variable that is not defined in the scope, JavaScript will throw &lt;code&gt;ReferenceError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In the example, we have defined variables using the &lt;code&gt;var&lt;/code&gt; keyword, but the same behavior would occur for variables defined via &lt;code&gt;let&lt;/code&gt; or &lt;code&gt;const&lt;/code&gt; keywords.&lt;/p&gt;

&lt;h3&gt;
  
  
  Block Scope
&lt;/h3&gt;

&lt;p&gt;Before ES2015, block scoping did not exist in JavaScript. Reason being that the only way to create variables was using the &lt;code&gt;var&lt;/code&gt; keyword.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; keywords are introduced, block scoping has become possible. Having block scoped variables helps a lot to prevent name pollution and accidental overrides of variables that are defined outside the block scope.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Not all variables can be block scoped&lt;/strong&gt;&lt;br&gt;
Variables defined using &lt;code&gt;var&lt;/code&gt; keyword can only be function scoped. When used inside a block, such a variable will leak its definition until the first function scope is reached.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Block scope is defined by &lt;code&gt;{}&lt;/code&gt; and can be put basically in any part of the program. Consider the following code.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&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;listOfTitles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;listOfReleaseYears&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;movie&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;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;releaseYear&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 🖨 Prints to the console&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listOfTitles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 🖨 Prints to the console&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listOfReleaseYears&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// 👇 Leaked definition&lt;/span&gt;
&lt;span class="c1"&gt;// 🖨 Prints to the console&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listOfTitles&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


&lt;span class="c1"&gt;// 🚫 ReferenceError: listOfReleaseYears is not defined&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;listOfReleaseYears&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Program above is making use of block scope by putting variables inside &lt;code&gt;{}&lt;/code&gt;. Inside the block scope, variables &lt;code&gt;listOfTitles&lt;/code&gt; and &lt;code&gt;listOfReleaseYears&lt;/code&gt; are defined, initialized and printed to console using &lt;code&gt;console.log&lt;/code&gt;. This works as expected, the content of both variables is printed to the console.&lt;/p&gt;

&lt;p&gt;When we try to print them again, outside the block scope, &lt;code&gt;listOfTitles&lt;/code&gt; will be printed but trying to reference &lt;code&gt;listOfReleaseYears&lt;/code&gt; will throw a &lt;code&gt;ReferenceError&lt;/code&gt;. Any idea why is this happening?&lt;/p&gt;

&lt;p&gt;If we look back at the code, notice that &lt;code&gt;listOfReleaseYears&lt;/code&gt; is defined using the &lt;code&gt;let&lt;/code&gt; keyword. This is the reason why the variable &lt;code&gt;listOfReleaseYears&lt;/code&gt; can not be used outside the block scope where it was initially created. On the other hand, &lt;code&gt;listOfTitles&lt;/code&gt; is defined using the &lt;code&gt;var&lt;/code&gt; keyword and it does not &lt;em&gt;see&lt;/em&gt; block scope.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;{}&lt;/code&gt; to create block scope might not be the most common way to do it. More often than not, block scopes will be created using statements like &lt;code&gt;if...else&lt;/code&gt; or &lt;code&gt;switch&lt;/code&gt;. In fact, &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;while&lt;/code&gt; loops are also block scoped. It often can catch developers off guard since they might think that the scope inside the loops behaves the same as the function scope, which is not the case.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&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;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&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;truncatedTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;trim&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="c1"&gt;// 🖨 Prints to the console&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truncatedTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// 🚫 ReferenceError: truncatedTitle is not defined&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truncatedTitle&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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;The variable &lt;code&gt;truncatedTitle&lt;/code&gt; is defined inside the block scope created by the &lt;code&gt;if&lt;/code&gt; statement, and it will be accessible as long as we reference it from the block scope. However, if we try to reference &lt;code&gt;truncatedTitle&lt;/code&gt; outside the block scope, in function scope, &lt;code&gt;ReferenceError&lt;/code&gt; will be thrown.&lt;/p&gt;

&lt;p&gt;To get a better picture, how block scope fits into our program, let's visualize it to show scope boundaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qiJgsMHJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5py87ox3b10yeo46tod.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qiJgsMHJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d5py87ox3b10yeo46tod.png" alt="Block scope defined inside function scope" width="314" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you look at the image and the source code, can you spot similarities? It should be obvious that scopes are defined by the source code. When you write your program, think about scopes as well. They will always be involved.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nested Scope
&lt;/h2&gt;

&lt;p&gt;In most non-trivial programs, chances are, many of the so-called &lt;em&gt;nested scopes&lt;/em&gt; will probably be created. Nested scope does not represent a new kind of scope, remember, there are only global, function and block scopes in JavaScript.&lt;/p&gt;

&lt;p&gt;The term &lt;strong&gt;nested scope&lt;/strong&gt; is used to describe a situation in which one scope is defined inside another scope. With that being said, we have already encountered nested scope in our previous examples.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&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;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&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;truncatedTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;trim&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truncatedTitle&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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;Can you spot which scope would be considered as nested? It is a block scope created by the &lt;code&gt;if&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;As we already know, the function &lt;code&gt;printTitle&lt;/code&gt; will create a function scope. However, it only has global scope as its outer scope. When scope is defined directly inside the global scope, it is usually not considered to be nested.&lt;/p&gt;

&lt;p&gt;The global scope is the outermost scope and any other scopes will, by default, be created inside it. For this reason, nesting usually implies a scope to be defined inside another scope that is not the global scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EGXEE2AN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yt63jedhg6l9rew1ihuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EGXEE2AN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yt63jedhg6l9rew1ihuy.png" alt="Visualized nested scope" width="498" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In our example, the block scope ticks all the boxes. It is nested inside another scope, created by the &lt;code&gt;printTitle&lt;/code&gt; function, and is not directly in the global scope.&lt;/p&gt;

&lt;p&gt;Many nested scopes can be defined through the program. This creates a hierarchical relationship between the scopes, where the inner scope has access to its own variables as well as the variables of outer scopes. This nesting of scopes allows for more complex programs to be built, as it guarantees separation of concerns and the creation of reusable code.&lt;/p&gt;

&lt;p&gt;Let's get back to our program and shed some light on scope related terminology. If we look from the perspective of the &lt;code&gt;printTitle&lt;/code&gt; function, we can say that the block scope, created by the &lt;code&gt;if&lt;/code&gt; statement, is a &lt;em&gt;child&lt;/em&gt; or &lt;em&gt;inner&lt;/em&gt; or &lt;em&gt;nested&lt;/em&gt; scope. In the same note, the function itself has the global scope as its &lt;em&gt;parent&lt;/em&gt; scope.&lt;/p&gt;

&lt;p&gt;Continuing, if we look from the perspective of the block scope, the function scope will be its &lt;em&gt;parent&lt;/em&gt; scope or the &lt;em&gt;first outer&lt;/em&gt; scope while the global scope will be it's &lt;em&gt;second outer&lt;/em&gt; scope.&lt;/p&gt;

&lt;p&gt;Another important term is &lt;em&gt;current scope&lt;/em&gt;. It refers to the scope where the JavaScript engine is currently executing code. So, hypothetically, if the engine is executing code in the block scope, we can refer to it as the current scope.&lt;/p&gt;

&lt;p&gt;If you find it a bit hard to understand nested scope and related terminology, try to read it again at a slower pace and don't give up so easily.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scope Chain
&lt;/h2&gt;

&lt;p&gt;So far, we have talked a lot about lexical scope and how it works, but there is one more important topic, closely related to lexical scope, that we need to cover.&lt;/p&gt;

&lt;p&gt;We have said that scope determines visibility and accessibility of variable and function declarations. You might be thinking, but how does it work? It has something to do with the so-called &lt;strong&gt;scope chain&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Scope chain is a mechanism used to determine the accessibility of variables and functions through the program. It defines the order of scope resolution during the runtime/execution phase. To better understand this, let's talk about scope chain &lt;em&gt;lookup&lt;/em&gt; first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lookup
&lt;/h3&gt;

&lt;p&gt;When a referenced variable or function can not be found in the current scope, the engine has to perform a search in the scope chain. This search is usually called scope chain &lt;strong&gt;lookup&lt;/strong&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt; &lt;span class="o"&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;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&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;truncatedTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;trim&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truncatedTitle&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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;Take a look at the function scope, the variable &lt;code&gt;movies&lt;/code&gt; is referenced, but it is not defined inside the function scope. The same is for the block scope, the variable &lt;code&gt;title&lt;/code&gt; is referenced, but it is not defined in the block scope.&lt;/p&gt;

&lt;p&gt;So how does the engine know what is the value of each of those variables? This is where scope chain lookup comes into play.&lt;/p&gt;

&lt;p&gt;When a variable or function is referenced, the engine starts at the current scope, looking for definition. Remember, current scope is the scope where the engine is currently executing the code. If the reference is not resolved in the current scope, the engine moves up in the scope chain searching for the reference. This process is repeated until the reference is resolved or the end of the scope chain is reached. In case that the reference could not be resolved, the engine will throw &lt;code&gt;ReferenceError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8ECqTVj_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0l7i92peizu7ullgv3d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8ECqTVj_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z0l7i92peizu7ullgv3d.png" alt="Visualization of scope chain lookup" width="431" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The variable &lt;code&gt;movies&lt;/code&gt; is referenced in the function scope. Since it is not defined in the same scope, it could not be found. The engine moves upwards in the scope chain and tries to resolve the reference. The next scope in the chain is the global scope. Since the variable &lt;code&gt;movies&lt;/code&gt; is defined in the global scope, the engine can resolve the reference and get the value.&lt;/p&gt;

&lt;p&gt;Similarly, when the engine tries to access &lt;code&gt;title&lt;/code&gt; from block scope, it has to do a lookup, go upwards in the scope chain trying to resolve the reference. In this case, the reference will be resolved in the function scope since the variable &lt;code&gt;title&lt;/code&gt; is defined in there.&lt;/p&gt;

&lt;p&gt;To recap, scope chain lookup refers to the process of searching through a list of scopes to find a referenced variable or function. The engine will start at the current scope and move upwards the scope chain until the reference is resolved or &lt;code&gt;ReferenceError&lt;/code&gt; is thrown.&lt;/p&gt;

&lt;h3&gt;
  
  
  Peek under the hood
&lt;/h3&gt;

&lt;p&gt;At this point, you should have a better understanding of lexical scope and scope chain. It's time to go one step deeper and look under the hood to see how the engine creates and maintains a scope chain.&lt;/p&gt;

&lt;p&gt;Scope chain is constructed and maintained during the execution phase. Just before the engine starts executing a piece of code, it needs to create a structure that holds variables and functions declarations. This structure is known as the lexical environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RX7Hr6tp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4n69b05gucdyemrup6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RX7Hr6tp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t4n69b05gucdyemrup6s.png" alt="Visualization of lexical environment" width="249" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before you ask, yes, lexical environment is related to lexical scope. It holds information about identifiers and their values that are defined in lexical scope.&lt;/p&gt;

&lt;p&gt;Each lexical environment has a reference to its parent environment, creating the scope chain. Do not be concerned about how the engine implements scope chain structure under the hood, after all, it's a job of the engine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--832biJtU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8psc8h2030z67bpmplas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--832biJtU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8psc8h2030z67bpmplas.png" alt="Scope chain constructed using references between lexical environments" width="880" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, when we have a good picture of how it works, let's use the same code from previous examples and walk through steps that the engine might take to create the scope chain.&lt;/p&gt;

&lt;p&gt;This will not be a detailed description on how the engine executes the code. Our goal here is to point out parts that are important for the scope chain creation.&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;var&lt;/span&gt; &lt;span class="nx"&gt;movies&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;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;District 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;releaseYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2009&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&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="s2"&gt;Sci-Fi&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="s2"&gt;Thriller&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;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Transformers: Age of Extinction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;releaseYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2014&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;genre&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Action&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="s2"&gt;Adventure&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="s2"&gt;Sci-Fi&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;printTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;index&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;movie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movies&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;movie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;12&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;truncatedTitle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&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="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;trim&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;truncatedTitle&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;printTitle&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;Obviously, code first needs to be parsed and compiled. At this point, the engine already knows about lexical scopes. Just before execution is started, the engine will create the global lexical environment.&lt;/p&gt;

&lt;p&gt;One important step, more commonly known as &lt;strong&gt;hoisting&lt;/strong&gt;, will occur during the creation of every lexical environment. The engine will hoist variables and functions to the top of their respective scopes and assign them their default values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hoisting behaves differently for variables defined using &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; keywords.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Taking the hosting into account, a freshly created global lexical environment, for our program, might look 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;{
  movies: undefined,
  printTitle: &amp;lt;ref. to function printTitle&amp;gt;,
  outer: null
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the engine starts executing the code, line by line. It will start with &lt;code&gt;var movies = [...]&lt;/code&gt;. Since the &lt;code&gt;movies&lt;/code&gt; variable is already created, courtesy of hoisting, the engine will create an array of objects in memory and save the reference to that array into the &lt;code&gt;movies&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Next, the engine will see the &lt;code&gt;function printTitle&lt;/code&gt; part of the code. However, there is nothing that needs to be done here. During hoisting, the engine has already created the &lt;code&gt;printTitle&lt;/code&gt; identifier and assigned, to it, a reference to the &lt;code&gt;printTitle&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;Good, the engine has made some progress and the global lexical environment looks like this now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  movies: &amp;lt;ref. to array&amp;gt;,
  printTitle: &amp;lt;ref. to function printTitle&amp;gt;,
  outer: null,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The variable &lt;code&gt;movies&lt;/code&gt; has been updated, and it now holds the reference to the array of movies saved in the memory.&lt;/p&gt;

&lt;p&gt;It is important to point out that the global lexical environment contains &lt;code&gt;movies&lt;/code&gt; and &lt;code&gt;printTitle&lt;/code&gt; identifiers only because we have put them into the global scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gkC5GW2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/de1dvrdxwrbbdk5rh7v9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gkC5GW2f--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/de1dvrdxwrbbdk5rh7v9.png" alt="Global lexical environment populated with identifiers from the global scope" width="249" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Did you notice the &lt;code&gt;outer&lt;/code&gt; identifier in the global lexical environment? This identifier is injected by the engine whenever a new lexical environment is created. It has a value of &lt;code&gt;null&lt;/code&gt; since the engine is executing code in the global scope.&lt;/p&gt;

&lt;p&gt;Continuing, the engine will see that we have called the &lt;code&gt;printTitle&lt;/code&gt; function passing number &lt;code&gt;1&lt;/code&gt; as an argument. Calling a function will trigger function execution. However, before the code inside the function gets executed, the lexical environment for the function itself will be created and hosting, for the function scope, will occur.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  index,
  movie: undefined,
  title: undefined,
  outer: &amp;lt;globalLexicalEnvironment&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the function has received &lt;code&gt;1&lt;/code&gt; as the first argument, the engine will immediately initialize the parameter &lt;code&gt;index&lt;/code&gt; and set its value to &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;outer&lt;/code&gt; identifier has reference to the global lexical environment. This reference allows the engine to access the global lexical environment. You know what that means? That's right, the engine has just created the scope chain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qie0FsT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enyv1rvek7h8vatknzs3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qie0FsT8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/enyv1rvek7h8vatknzs3.png" alt="Scope chain created by linking two lexical environment" width="555" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When executing &lt;code&gt;var movie = movies[index]&lt;/code&gt; the engine will see that the variable &lt;code&gt;movies&lt;/code&gt; does not exist in the current scope, and it will use the reference, saved in the &lt;code&gt;outer&lt;/code&gt; identifier, to access the global lexical environment. Now, it will start looking for the &lt;code&gt;movies&lt;/code&gt; identifier and resolve its value. Does this sound familiar? The engine has just performed a scope chain lookup.&lt;/p&gt;

&lt;p&gt;The variable &lt;code&gt;movies&lt;/code&gt; holds the reference that points to the movies array saved in memory. According to our code, &lt;code&gt;movies[index]&lt;/code&gt;, the engine will take the object on the index &lt;code&gt;1&lt;/code&gt; and save its reference into the &lt;code&gt;movie&lt;/code&gt; variable. At the end, reference to the second object in the &lt;code&gt;movies&lt;/code&gt; array is saved into the &lt;code&gt;movie&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;Continuing, statement &lt;code&gt;var title = movie.title&lt;/code&gt; is next to execute. To initialize the &lt;code&gt;title&lt;/code&gt; variable, the engine will need to resolve the &lt;code&gt;movie&lt;/code&gt; identifier. Since it's declared in the local scope, scope chain lookup will not be required. As we already know, the variable &lt;code&gt;movie&lt;/code&gt; holds reference to the &lt;code&gt;movies[1]&lt;/code&gt; object. The engine will take the value from the property &lt;code&gt;title&lt;/code&gt; which is string &lt;code&gt;"Transformers: Age of Extinction"&lt;/code&gt; and save it into the &lt;code&gt;title&lt;/code&gt; variable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reference or value?&lt;/strong&gt;&lt;br&gt;
It is very important to know when the engine is passing/returning reference and when the actual value. In general, only primitive data types are passed by value, and non-primitive ones are passed as a reference.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The engine has just executed the first two lines inside the function. Here is how the local (function) lexical environment looks like now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  index: 1,
  movie: &amp;lt;ref to movies[1]&amp;gt;,
  title: “Transformers: Age of Extinction”,
  outer: &amp;lt;globalLexicalEnvironment&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both &lt;code&gt;movie&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; are updated. Notice that the &lt;code&gt;movie&lt;/code&gt; variable now holds reference to the &lt;code&gt;movies[1]&lt;/code&gt; object, while &lt;code&gt;title&lt;/code&gt; holds the string value &lt;code&gt;"Transformers: Age of Extinction"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Woah, the engine is flying through our program and we are already in the &lt;code&gt;if (title.length &amp;gt; 12)&lt;/code&gt; part of the code. When the engine checks &lt;code&gt;title.length &amp;gt; 12&lt;/code&gt;, it will get &lt;code&gt;true&lt;/code&gt; as a result. Remember, &lt;code&gt;title&lt;/code&gt; is still part of local (function) scope, so no scope chain lookup is required.&lt;/p&gt;

&lt;p&gt;Because of the truthful condition, the engine will create a new lexical environment for the &lt;code&gt;if&lt;/code&gt; statement. Remember from before, this lexical environment is created only because we used &lt;code&gt;const&lt;/code&gt; inside the &lt;code&gt;if&lt;/code&gt; statement.&lt;/p&gt;

&lt;p&gt;After creating a new lexical environment for the &lt;code&gt;if&lt;/code&gt; block, taking hoisting into consideration, the engine will give us something 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;{
  truncatedTitle,
  outer: &amp;lt;functionLexicalEnvironment&amp;gt;,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The engine has created yet another lexical environment, and look where does the &lt;code&gt;outer&lt;/code&gt; identifier points to? That's right, to the function lexical environment, and now we have scope chain that consists of 3 lexical environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X3jjvvKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r20nkw2qc9sgw4h6b798.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X3jjvvKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r20nkw2qc9sgw4h6b798.png" alt="Scope chain with three lexical environments" width="862" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice that &lt;code&gt;truncatedTitle&lt;/code&gt; is not initialized with any value. At the moment, &lt;code&gt;truncatedTitle&lt;/code&gt; is in the so-called &lt;strong&gt;TDZ&lt;/strong&gt; (Temporal Dead Zone). The engine knows about the &lt;code&gt;truncatedTitle&lt;/code&gt; variable, but it can not be used before it's initialized or &lt;code&gt;ReferenceError&lt;/code&gt; error will be thrown. This only happens when using variables declared with &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The engine starts executing the first line of code inside the block &lt;code&gt;const truncatedTitle = `${title.substring(0, 12).trim()}...`&lt;/code&gt;. Here is where the engine will initialize the &lt;code&gt;truncatedTitle&lt;/code&gt; variable and, after this point in time, TDZ for &lt;code&gt;truncatedTitle&lt;/code&gt; ends.&lt;/p&gt;

&lt;p&gt;The engine will search the scope chain to resolve the &lt;code&gt;title&lt;/code&gt; identifier and get the value. This identifier will be resolved in the function scope. Because of &lt;code&gt;substring&lt;/code&gt; and &lt;code&gt;trim&lt;/code&gt; string methods, the engine will return the first 12 characters, removing potential empty space along the way. At the end, the value saved into the &lt;code&gt;truncatedTitle&lt;/code&gt; will be string &lt;code&gt;"Transformers..."&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  truncatedTitle: “Transformers...”,
  outer: &amp;lt;functionLexicalEnvironment&amp;gt;,
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just before the end of the block scope, &lt;code&gt;console.log(truncatedTitle)&lt;/code&gt; will be executed and the value of the &lt;code&gt;truncatedTitle&lt;/code&gt; variable will be printed to the console.&lt;/p&gt;

&lt;p&gt;Continuing, the engine has to exit the block scope. Usually, when the engine exits a lexical scope, the lexical environment for that scope is typically destroyed and garbage-collected by the engine's memory management system. This means that any variables and functions declared in that scope are no longer accessible and do not occupy memory. This is an automatic process that happens in the background and usually the developer does not have to worry about it.&lt;/p&gt;

&lt;p&gt;Taking that into account, when the engine exits the block scope, the block lexical environment will be destroyed, which means that variable &lt;code&gt;truncatedTitle&lt;/code&gt; no longer exists and its value &lt;code&gt;"Transformers..."&lt;/code&gt; is removed from the memory.&lt;/p&gt;

&lt;p&gt;If we take a look at the scope chain, the lexical environment created for the block scope is removed from the scope chain. The engine will manage this automatically when the lexical environment is destroyed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f2flGmCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0l68bvcy8xd5x65g1onq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f2flGmCh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0l68bvcy8xd5x65g1onq.png" alt="Scope chain after removing lexical environment created for the block scope" width="555" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next in order of execution is &lt;code&gt;console.log(title)&lt;/code&gt;. The engine is executing in the function scope again. This means that the variable &lt;code&gt;title&lt;/code&gt; is accessible from the local lexical environment and scope chain lookup is not required. When the engine is done executing this line, the value of the variable &lt;code&gt;title&lt;/code&gt; will be printed to the console.&lt;/p&gt;

&lt;p&gt;Continuing, the engine has to exit the function and garbage-collection will kick in by destroying the lexical environment and releasing used memory. Now, if we look at the scope chain, it has only one lexical environment left.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yKrxzhqC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ratnd49uh1v91nlal8b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yKrxzhqC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ratnd49uh1v91nlal8b.png" alt="Scope chain after removing lexical environment created for the function scope" width="249" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, there is no code left to be executed, and the engine has reached the end of our program. It terminates the process and releases all the resources that were used during execution time, including memory and CPU time.&lt;/p&gt;

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

&lt;p&gt;Lexical scope and scope chain are fundamental concepts in JavaScript. Lexical scope determines which variables and functions are accessible within a certain code block.&lt;/p&gt;

&lt;p&gt;The scope chain, on the other hand, is an internal structure managed and used by the JavaScript engine to resolve variables and functions during runtime, following the hierarchy of lexical scopes. Understanding these concepts is important for writing efficient and effective JavaScript code.&lt;/p&gt;

&lt;p&gt;I tried to give more details about lexical scope and related terminology, but also to dive deeper into scope chain management and explain how it works under the hood. I really hope that this was helpful and you have more knowledge about this topic than before reading this article.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://ramomujagic.com/blog/"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>scope</category>
    </item>
    <item>
      <title>Bulk install VS Code extensions</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Mon, 16 Jan 2023 18:41:45 +0000</pubDate>
      <link>https://dev.to/rmmgc/bulk-install-vs-code-extensions-3omc</link>
      <guid>https://dev.to/rmmgc/bulk-install-vs-code-extensions-3omc</guid>
      <description>&lt;p&gt;If you are reading this, you probably already know what VS Code and VS Code extensions are. Usual way to install extensions is through VS Code Interface. It is really easy and intuitive. However, every extension needs to be installed one by one.&lt;/p&gt;

&lt;p&gt;This is great if you need to install one extension at the time, which is usually the case, but what if you need to install 20 or more extensions? It can become a time consuming process.&lt;/p&gt;

&lt;p&gt;You might wonder, &lt;em&gt;why would I ever need to install 20 or more extensions at the time?&lt;/em&gt; Let's answer this question in the next section.&lt;/p&gt;

&lt;h2&gt;
  
  
  The reason why
&lt;/h2&gt;

&lt;p&gt;Recently, I needed to setup a new working environment and basically replicate everything that I already have on the old machine on the new one.&lt;/p&gt;

&lt;p&gt;For some, this can be fun and interesting. It also gives you an opportunity to add some changes to your setup that you didn't want to do before. But when you do it often or when you are happy with your current setup, it can be really tedious to do it again from scratch.&lt;/p&gt;

&lt;p&gt;Anyways, eventually, I needed to setup VS Code to be exactly the same as on the old machine. However, I have noticed that I could not install extensions all at once. Since I have more than 20 extensions that I needed to install, I did not want to do it manually, one by one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bulk install script
&lt;/h2&gt;

&lt;p&gt;I decided to make a script that can automate the extensions installation process. For me, it would be good enough to loop over a list of extensions and install them.&lt;/p&gt;

&lt;p&gt;I spent some time trying out the &lt;code&gt;code&lt;/code&gt; command and possible options. Luckily, it is possible to use the &lt;code&gt;code --list-extensions&lt;/code&gt; command to list all installed extensions and also &lt;code&gt;code --install-extension &amp;lt;extension_id&amp;gt;&lt;/code&gt; to install the extension.&lt;/p&gt;

&lt;p&gt;Lastly, I decided to make it a bit more robust and added some logging so it's easy to see what the script is doing. Source code is &lt;a href="https://github.com/rmmgc/vscode-extensions-bulk-install.git"&gt;available here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;First, you need to prepare a &lt;code&gt;.txt&lt;/code&gt; file that will be used as an input for the script. This file should contain a list of all VS Code extensions, one per line. Here is a sample of how file content should look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
akamud.vscode-theme-onedark
akamud.vscode-theme-onelight
dbaeumer.vscode-eslint
eamodio.gitlens
esbenp.prettier-vscode
formulahendry.auto-rename-tag
mikestead.dotenv
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every extension must be in &lt;code&gt;&amp;lt;publisher&amp;gt;.&amp;lt;name&amp;gt;&lt;/code&gt; format. Make sure that the file is correctly formatted and that there are no extra spaces or blank lines in the file.&lt;/p&gt;

&lt;p&gt;Alternatively, you can use a &lt;code&gt;code&lt;/code&gt; command to extract the list of extensions from your current VS Code installation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--list-extensions&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; extensions-list.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the command is executed, it will generate a list of all installed extensions and save them into the &lt;code&gt;extensions-list.txt&lt;/code&gt; file. You can change the file name in the command if you want.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the script
&lt;/h3&gt;

&lt;p&gt;Next step would be to run the script and use the previously created file as an input. It can all be done in just one command like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/rmmgc/vscode-extensions-bulk-install/main/bulk-install.sh | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &amp;lt;path_to_input_file&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;For the script to work properly, VS Code needs to be installed and the &lt;code&gt;code&lt;/code&gt; command must be exported on the &lt;code&gt;PATH&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When the command is executed, it will get text content of the script from the URL and pipe the output to the &lt;code&gt;sh&lt;/code&gt; command. The script file itself will not be saved on your machine. Additionally, the path to the input file is passed as an argument to the script.&lt;/p&gt;

&lt;p&gt;Make sure to replace &lt;code&gt;path_to_input_file&lt;/code&gt; with a path to the input file that has a list of extensions.&lt;/p&gt;

&lt;p&gt;After execution, you should see a detailed log in the terminal. It might look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...

🔧 Working on dbaeumer.vscode-eslint extension.
✅ Extension already installed.
Skipping further steps.

🔧 Working on formulahendry.auto-rename-tag extension.
Running: code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; formulahendry.auto-rename-tag.
Installing extensions...
Installing extension &lt;span class="s1"&gt;'formulahendry.auto-rename-tag'&lt;/span&gt;...
&lt;span class="o"&gt;(&lt;/span&gt;node:93018&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;DEP0005] DeprecationWarning: Buffer&lt;span class="o"&gt;()&lt;/span&gt; is deprecated due to security and usability issues. Please use the Buffer.alloc&lt;span class="o"&gt;()&lt;/span&gt;, Buffer.allocUnsafe&lt;span class="o"&gt;()&lt;/span&gt;, or Buffer.from&lt;span class="o"&gt;()&lt;/span&gt; methods instead.
&lt;span class="o"&gt;(&lt;/span&gt;Use &lt;span class="sb"&gt;`&lt;/span&gt;Electron &lt;span class="nt"&gt;--trace-deprecation&lt;/span&gt; ...&lt;span class="sb"&gt;`&lt;/span&gt; to show where the warning was created&lt;span class="o"&gt;)&lt;/span&gt;
Extension &lt;span class="s1"&gt;'formulahendry.auto-rename-tag'&lt;/span&gt; v0.1.10 was successfully installed.
✅ Extension installed successfully.

🔧 Working on mikestead.dotenv extension.
✅ Extension already installed.
Skipping further steps.

💡 Check the logs above &lt;span class="k"&gt;for &lt;/span&gt;detailed report.
🎉 Successfully finished.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All missing extensions should be installed. In case some extensions were already installed before running the script, they will be skipped.&lt;/p&gt;

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

&lt;p&gt;It became boring always installing VS Code extensions whenever setting up a new working environment. That's why I decided to create and share a script that can help to speed up this process a little bit.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://ramomujagic.com/blog/"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>bash</category>
      <category>tooling</category>
    </item>
    <item>
      <title>VS Code extensions I always use</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Mon, 19 Dec 2022 18:37:22 +0000</pubDate>
      <link>https://dev.to/rmmgc/vs-code-extensions-i-always-use-3439</link>
      <guid>https://dev.to/rmmgc/vs-code-extensions-i-always-use-3439</guid>
      <description>&lt;p&gt;If you are working with JS, chances are that you are already using VS Code. It is the most popular editor for JS development. Some of the reasons why VS Code is so popular is the fact that it costs nothing - completely open source, easy to use, fully customizable, really fast and a joy to work with.&lt;/p&gt;

&lt;p&gt;Since VS Code is so popular there are many extensions created to extend its functionality. From so many extensions available to you it might be hard to choose which ones to use. I decided to make a list of extensions I always use on every JS project no matter the requirements.&lt;/p&gt;

&lt;p&gt;This list of extensions is not based on a particular JS framework or library like &lt;em&gt;Vue&lt;/em&gt; or &lt;em&gt;React&lt;/em&gt;, so no snippet extensions, but rather on extensions that every JS developer might find useful.&lt;/p&gt;

&lt;p&gt;To make it easier, I have decided to group extensions into two categories, &lt;em&gt;UI Extensions&lt;/em&gt; and &lt;em&gt;Utility Extensions&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  UI Extensions
&lt;/h2&gt;

&lt;p&gt;Under this category, I will mention extensions that actually change the appearance of &lt;em&gt;User Interface&lt;/em&gt; inside VS Code. They will make your editor stand out and look much nicer than the default you get after installing VS Code, even though the default one looks pretty good to begin with. After all, having a nice working environment is really important for productivity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atom One Dark Theme
&lt;/h3&gt;

&lt;p&gt;For me, there is no better dark theme than &lt;a href="https://marketplace.visualstudio.com/items?itemName=akamud.vscode-theme-onedark" rel="noopener noreferrer"&gt;Atom One Dark Theme&lt;/a&gt;. It is just perfect in any way. Nice color scheme, good contrast between colors, nice to look at, it basically ticks all the boxes for me. There is a reason why this extension has more that &lt;strong&gt;3.8M&lt;/strong&gt; downloads, at the time of writing.&lt;/p&gt;

&lt;p&gt;This is of course highly opinionated. There are many other good dark themes that could be a better fit for you. I would say, If you don't like this theme, go ahead and try the others until you find something you like. To know what fits you the best you need to try it first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Atom One Light Theme
&lt;/h3&gt;

&lt;p&gt;I personally do not use light themes often. But there are some situations that I can find myself in where a light theme is better suited than the dark one.&lt;/p&gt;

&lt;p&gt;I work for a company that has large open offices with a lot of natural light. When working in a bright environment, like this, it is much easier to read text/code when using a light theme.&lt;/p&gt;

&lt;p&gt;When a light theme is needed, I go for &lt;a href="https://marketplace.visualstudio.com/items?itemName=akamud.vscode-theme-onelight" rel="noopener noreferrer"&gt;Atom One Light Theme&lt;/a&gt; just because of the similarities with Atom One Dark Theme.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To quickly switch between themes, hit &lt;strong&gt;Command/Ctrl&lt;/strong&gt; + &lt;strong&gt;K&lt;/strong&gt; + &lt;strong&gt;T&lt;/strong&gt; to open the &lt;em&gt;Theme picker&lt;/em&gt; where you can select the desired theme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  VS Code Icons
&lt;/h3&gt;

&lt;p&gt;When it comes to icons I always go for &lt;a href="https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons" rel="noopener noreferrer"&gt;VS Code Icons&lt;/a&gt;. It is very popular extension as well with over &lt;strong&gt;12.5M&lt;/strong&gt; downloads.&lt;/p&gt;

&lt;p&gt;This extension has a large collection of images for basically every file type and even some specially named directories will have a dedicated icon.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;To quickly switch between icon themes, hit &lt;strong&gt;Command/Ctrl&lt;/strong&gt; + &lt;strong&gt;Shift&lt;/strong&gt; + &lt;strong&gt;P&lt;/strong&gt; to open the &lt;em&gt;Command Palette&lt;/em&gt;. Type &lt;em&gt;"icon theme"&lt;/em&gt; and select the first option. &lt;em&gt;Icon Theme picker&lt;/em&gt; will show up where you can select the desired icon theme.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Utility Extensions
&lt;/h2&gt;

&lt;p&gt;Let's take a look at non-ui extensions. These extensions should actually help to make you faster and write better code. There are a lot of different kinds of extensions under this category, but for sake of simplicity, I just call them utility extensions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto Rename Tag
&lt;/h3&gt;

&lt;p&gt;This extension is really simple, it only does one job. &lt;a href="https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag" rel="noopener noreferrer"&gt;Auto Rename Tag&lt;/a&gt; will automatically rename paired HTML/XML tags. Job it does may seem trivial, but this extension is really a time saver.&lt;/p&gt;

&lt;h3&gt;
  
  
  DotENV
&lt;/h3&gt;

&lt;p&gt;More often than not, your projects will require &lt;code&gt;.env&lt;/code&gt; files where &lt;em&gt;Environment Variables&lt;/em&gt; can be provided. This is probably more important to people that are working on &lt;em&gt;Node.js&lt;/em&gt; applications, but also modern frontend frameworks might require it.&lt;/p&gt;

&lt;p&gt;To bring syntax highlighting for &lt;code&gt;.env&lt;/code&gt; files, in VS Code, you can use &lt;a href="https://marketplace.visualstudio.com/items?itemName=mikestead.dotenv" rel="noopener noreferrer"&gt;DotENV&lt;/a&gt; extension. After installing extensions, all your &lt;code&gt;.env&lt;/code&gt; files should have proper syntax highlighting.&lt;/p&gt;

&lt;h3&gt;
  
  
  ESLint
&lt;/h3&gt;

&lt;p&gt;This is one of the most popular extensions on the VS Code marketplace and for a good reason. &lt;a href="https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint" rel="noopener noreferrer"&gt;ESLint extension&lt;/a&gt; integrates &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;ESLint&lt;/a&gt;, the most popular JS linter, into VS Code.&lt;/p&gt;

&lt;p&gt;For this extension to properly work, you need to have the &lt;code&gt;eslint&lt;/code&gt; npm package installed in your workspace or globally on your machine.&lt;/p&gt;

&lt;p&gt;I would recommend always installing &lt;code&gt;eslint&lt;/code&gt; into workspace rather than doing it globally. Navigate to your project/workspace and run the following command.&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; &lt;span class="nt"&gt;-D&lt;/span&gt; eslint
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command will install &lt;code&gt;eslint&lt;/code&gt; as a dev dependency. You can fine tune how JS linter integrates with your project by creating a &lt;code&gt;.eslintrc.js&lt;/code&gt; configuration file. Find out more information about it on the &lt;a href="https://eslint.org/docs/latest/user-guide/configuring/configuration-files" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prettier
&lt;/h3&gt;

&lt;p&gt;Another very popular extension is &lt;a href="https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode" rel="noopener noreferrer"&gt;Prettier&lt;/a&gt;. It is an opinionated code formatter that enforces consistent code style throughout the whole project.&lt;/p&gt;

&lt;p&gt;You might wonder, why would I need a code formatter if I write code in a consistent way?&lt;br&gt;&lt;br&gt;
If you work alone on the project and you don't really care if your code is consistently formatted or not, you can get by without it.&lt;/p&gt;

&lt;p&gt;Where &lt;code&gt;prettier&lt;/code&gt; really shines is when you make your project open-source, to allow more people to contribute, or when you work in a team.&lt;/p&gt;

&lt;p&gt;No one writes code in the same way. You can put &lt;code&gt;;&lt;/code&gt; at the end of the line, but someone else will leave it out. This is where &lt;code&gt;prettier&lt;/code&gt; comes into play, to fix those kinds of inconsistencies.&lt;/p&gt;

&lt;p&gt;This extension requires the &lt;code&gt;prettier&lt;/code&gt; npm package to be installed. Although it can be configured to work with global installation of &lt;code&gt;prettier&lt;/code&gt;, it is recommended to use local installation. Navigate to your project/workspace and run the following command.&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; &lt;span class="nt"&gt;-D&lt;/span&gt; prettier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Command will install &lt;code&gt;prettier&lt;/code&gt; as a dev dependency. You can fine tune how &lt;code&gt;prettier&lt;/code&gt; integrates with your project by creating a &lt;code&gt;.prettierrc.js&lt;/code&gt; configuration file. Find out more information about it on the &lt;a href="https://prettier.io/docs/en/configuration.html" rel="noopener noreferrer"&gt;official website&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitLens
&lt;/h3&gt;

&lt;p&gt;One of the best extensions that supercharges VS Code with amazing &lt;code&gt;git&lt;/code&gt; support is &lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens" rel="noopener noreferrer"&gt;GitLens&lt;/a&gt;. Feature list is crazy long and it really helps better understand what is going on especially if working in a team.&lt;/p&gt;

&lt;p&gt;However, if you do not need most of the features that GitLens provides, I would recommend using different &lt;code&gt;git&lt;/code&gt; related extensions that might be simpler to work with.&lt;/p&gt;

&lt;h3&gt;
  
  
  npm Intellisense
&lt;/h3&gt;

&lt;p&gt;When working on a JS project, chances are that you will have a lot of third-party packages installed. To make it easy to import all those modules, you can use &lt;a href="https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense" rel="noopener noreferrer"&gt;npm Intellisense&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This extension has one job. It will autocomplete npm modules in import statements. You just need to start typing the name of the module you want to import and extension will provide you with best matching suggestions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Thunder Client
&lt;/h3&gt;

&lt;p&gt;Sooner or later, you will have to test some API and check which kind of data it returns and how it behaves. Before, the most popular tool for this kind of job was Postman, but now you can do it straight from VS Code itself without installing a dedicated application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=rangav.vscode-thunder-client" rel="noopener noreferrer"&gt;Thunder Client&lt;/a&gt; is the REST API client that I always use. It is lightweight, has a simple to use interface and really easy to work with.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tabnine
&lt;/h3&gt;

&lt;p&gt;Let's finish this list with &lt;a href="https://marketplace.visualstudio.com/items?itemName=TabNine.tabnine-vscode" rel="noopener noreferrer"&gt;Tabnine&lt;/a&gt;. This is an AI code assistant that, essentially, does code completions. &lt;/p&gt;

&lt;p&gt;Personally, in the beginning I was a bit skeptical about AI assistants, but this one turned out to be pretty good. I can genuinely say that it does help save some time with code completions that it provides.&lt;/p&gt;

&lt;p&gt;There is also a Pro version and this one is, obviously, not free. The Pro version is much more powerful and has more useful features.&lt;/p&gt;

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

&lt;p&gt;VS Code is an amazing editor with a lot of features, but what makes it special, in my eyes, is the extensions marketplace. There are so many third-party extensions out there created for almost anything.&lt;/p&gt;

&lt;p&gt;I have listed my favorite extensions that I always use, on every project. However, based on the project, I usually install additional extensions which are, most of the time, project specific. If you do the same, make sure to remove unused extensions after. It can make VS Code a bit faster.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://ramomujagic.com/blog/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Understanding equality in JavaScript</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Mon, 28 Nov 2022 18:12:10 +0000</pubDate>
      <link>https://dev.to/rmmgc/understanding-equality-in-javascript-47ol</link>
      <guid>https://dev.to/rmmgc/understanding-equality-in-javascript-47ol</guid>
      <description>&lt;p&gt;We have all been there… You compare two values using &lt;code&gt;==&lt;/code&gt;, receive a totally unexpected result and wonder &lt;em&gt;WT*&lt;/em&gt; is going on?! - Just Equality &lt;code&gt;==&lt;/code&gt; operator at its finest.&lt;/p&gt;

&lt;p&gt;Equality &lt;code&gt;==&lt;/code&gt; operator has the following syntax.&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;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It takes two operands, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;, converts them into the same type, compares them by value and returns a &lt;code&gt;Boolean&lt;/code&gt; result.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Always use Strict Equality &lt;code&gt;===&lt;/code&gt; operator. There is literally no benefit in using &lt;code&gt;==&lt;/code&gt; instead of &lt;code&gt;===&lt;/code&gt;, except if your goal is to introduce bugs to your codebase.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But you did not come here so I can tell you to start using &lt;code&gt;===&lt;/code&gt;. Just look at the code below. You want to know how it can possibly be explained, don't you? - And yes, you should know it. After all, you are working with JavaScript and this is a JavaScript feature.&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="dl"&gt;''&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;             &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;               &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;              &lt;span class="c1"&gt;// Result: true&lt;/span&gt;

&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;    &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;         &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;     &lt;span class="c1"&gt;// Result: true&lt;/span&gt;

&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;               &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;             &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&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="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a,b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;   &lt;span class="c1"&gt;// Result: true&lt;/span&gt;

&lt;span class="kc"&gt;NaN&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;            &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\r\t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;         &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  IsLooselyEqual algorithm
&lt;/h2&gt;

&lt;p&gt;When you use &lt;code&gt;==&lt;/code&gt;, under the hood, this algorithm kicks in and gives the result of comparison. So, yes, here lies the cure for our pain.&lt;/p&gt;

&lt;p&gt;This algorithm is described in &lt;a href="https://tc39.es/ecma262/multipage/abstract-operations.html#sec-islooselyequal" rel="noopener noreferrer"&gt;ECMAScript specification&lt;/a&gt; and basically every &lt;a href="https://en.wikipedia.org/wiki/JavaScript_engine" rel="noopener noreferrer"&gt;JavaScript engine&lt;/a&gt; has to implement it as described.&lt;/p&gt;

&lt;p&gt;It is common to represent algorithms with some kind of graph or flow chart, but since I am very bad at drawing, I present to you this magnificent &lt;a href="https://en.wikipedia.org/wiki/Pseudocode" rel="noopener noreferrer"&gt;pseudocode&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Take two operands, `x` and `y`, as an input

If type of `x` is the same as type of `y`
  If type of `x` is `Undefined`
    return `true`
  If type of `x` is `Null`
    return `true`

  If type of `x` is `Number`
    If `x` is `NaN`
      return `false`
    If `y` is `NaN`
      return `false`
    If `x` is the same as `y`
      return `true`
    If `x` is `-0` and `y` is `+0`
      return `true`
    if `x` is `+0` and `y` is `-0`
      return `true`
    return `false`

  If the type of `x` is `String`
    If `x` and `y` are exactly the same sequence of characters
      return `true`
    return `false`

  If the type of `x` is `Boolean`
    If `x` and `y` are both `true`
      return `true`
    If `x` and `y` are both `false`
      return `true`
    return `false`

  If `x` and `y` refer to the same object
    return `true`

  return `false`

If `x` is `null` and `y` is `undefined`
  return `true`
If `x` is `undefined` and `y` is `null`
  return `true`.

If type of `x` is `Number` and type of `y` is `String`
  Convert `y` to `Number`
  Return the result of the comparison `x == y`
If type of `x` is `String` and type of `y` is `Number`
  Convert `x` to `Number`
  Return the result of the comparison `x == y`

If type of `x` is `Boolean`
  Convert `x` to `Number`
  Return the result of the comparison `x == y`
If type of `y` is `Boolean`
  Convert `y` to `Number`
  Return the result of the comparison `x == y`

If type of `x` is either `String` or `Number` and type of `y` is `Object`
  Convert `y` to primitive value
  Return the result of the comparison `x == y`
If type of `x` is `Object` and type of `y` is either `String` or `Number`
  Convert `x` to primitive value
  Return the result of the comparison `x == y`

Return `false`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Keep in mind that some parts of the algorithm are missing in pseudocode representation. If you want to see detailed specifications, check it out on ECMAScript website.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, I know, it's just a bunch of if statements and conversions. This conversion part is really what's important. You see, when types are the same, &lt;code&gt;==&lt;/code&gt; behaves exactly the same as the &lt;code&gt;===&lt;/code&gt; operator. Important difference is that &lt;code&gt;==&lt;/code&gt; enforces coercion when types are different.&lt;/p&gt;

&lt;p&gt;Coercion is a fancy JavaScript term used when we talk about converting from one value type to another, like from string to number. Coercion plays an important role in &lt;code&gt;==&lt;/code&gt; comparison.&lt;/p&gt;

&lt;p&gt;If you don't want to remember the whole algorithm, think about it in this way. If operands do not have the same type, they are converted to &lt;code&gt;Number&lt;/code&gt;. When types are the same, operands are compared by value.&lt;/p&gt;

&lt;h2&gt;
  
  
  Object to primitive
&lt;/h2&gt;

&lt;p&gt;One more important thing, before we focus on some examples, is conversion of the &lt;code&gt;Object&lt;/code&gt; type values to primitive values.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In JavaScript, there are 7 primitive values: &lt;em&gt;string&lt;/em&gt;, &lt;em&gt;number&lt;/em&gt;, &lt;em&gt;bigint&lt;/em&gt;, &lt;em&gt;boolean&lt;/em&gt;, &lt;em&gt;undefined&lt;/em&gt;, &lt;em&gt;null&lt;/em&gt; and &lt;em&gt;symbol&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Value with the type of &lt;code&gt;Object&lt;/code&gt; can automatically be converted to primitive value by &lt;code&gt;==&lt;/code&gt; operator. This conversion will happen when the type of one operand is &lt;code&gt;Object&lt;/code&gt; while the other operand has one of primitive types.&lt;/p&gt;

&lt;p&gt;When converting &lt;code&gt;Object&lt;/code&gt; to primitive value, JavaScript will do a couple of things. It will first try to call the built-in prototype method &lt;code&gt;valueOf&lt;/code&gt;. If &lt;code&gt;valueOf&lt;/code&gt; does not return a primitive value, the built-in prototype method &lt;code&gt;toString&lt;/code&gt; will be called next.&lt;/p&gt;

&lt;p&gt;As almost anything in JavaScript this behavior has a couple of edge cases and it can be modified and overridden, but you don't have to worry about it for now.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples
&lt;/h2&gt;

&lt;p&gt;Still remember that code sample from the beginning? Let's cover it line by line, now when we know how the algorithm works.&lt;/p&gt;

&lt;p&gt;I will make one assumption here. Operand on the left side of &lt;code&gt;==&lt;/code&gt; will be called &lt;code&gt;x&lt;/code&gt; and the operand on the right side will be called &lt;code&gt;y&lt;/code&gt;. With that out of the way, let's get started.&lt;/p&gt;

&lt;p&gt;Keep in mind, if operands do not have the same type, &lt;code&gt;==&lt;/code&gt; will enforce &lt;strong&gt;type conversion&lt;/strong&gt; as long as operands have different types. Only then will operands be compared by value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 01
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;''&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;             &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is pretty simple. Both operands have the same type, &lt;code&gt;String&lt;/code&gt;. This means that operands will be compared by value. Since values are not the same, the result is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 02
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;               &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type of operand &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;Number&lt;/code&gt; and type of operand &lt;code&gt;y&lt;/code&gt; is &lt;code&gt;String&lt;/code&gt;. Types are not the same and &lt;code&gt;y&lt;/code&gt; will be converted to &lt;code&gt;Number&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Empty string &lt;code&gt;''&lt;/code&gt; converted to &lt;code&gt;Number&lt;/code&gt;, will be &lt;code&gt;0&lt;/code&gt;. Test it by running &lt;code&gt;Number('')&lt;/code&gt; in your browser's console.&lt;/p&gt;

&lt;p&gt;When conversion is completed operands will be compared by value. Since values are the same, &lt;code&gt;0&lt;/code&gt; is indeed equal to &lt;code&gt;0&lt;/code&gt;, result will be &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 03
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;              &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type of operand &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;Number&lt;/code&gt; and the type of operand &lt;code&gt;y&lt;/code&gt; is &lt;code&gt;String&lt;/code&gt;. Operand &lt;code&gt;y&lt;/code&gt; will be converted to &lt;code&gt;Number&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When &lt;code&gt;'0'&lt;/code&gt; is converted to &lt;code&gt;Number&lt;/code&gt;, its value is going to be &lt;code&gt;0&lt;/code&gt;. Test it by running &lt;code&gt;Number('0')&lt;/code&gt; in your browser's console.&lt;/p&gt;

&lt;p&gt;When conversion is completed operands will be compared by value. Since values are the same, &lt;code&gt;0&lt;/code&gt; is indeed equal to &lt;code&gt;0&lt;/code&gt;, result will be &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 04
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;    &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;         &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;     &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I grouped these examples together since the reasoning for this behavior, in all of them, is pretty much the same.&lt;/p&gt;

&lt;p&gt;According to the algorithm, &lt;code&gt;undefined&lt;/code&gt; can only be equal to &lt;code&gt;undefined&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;. Same is for &lt;code&gt;null&lt;/code&gt;, it can only be equal to &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. Because of this, comparing them to &lt;code&gt;false&lt;/code&gt; will always result in &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 05
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;               &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operand &lt;code&gt;x&lt;/code&gt; is the type of &lt;code&gt;Object&lt;/code&gt; and the type of operand &lt;code&gt;y&lt;/code&gt; is &lt;code&gt;String&lt;/code&gt;. As we already know, before they can be compared by value, type conversion is going to happen. In this case, operand &lt;code&gt;x&lt;/code&gt; will be converted to a primitive value. This means &lt;code&gt;Object&lt;/code&gt; to primitive conversion will kick in.&lt;/p&gt;

&lt;p&gt;So, let's see how the conversion of &lt;code&gt;[]&lt;/code&gt; to primitive value looks like. Method &lt;code&gt;valueOf&lt;/code&gt; is going to be called on &lt;code&gt;[]&lt;/code&gt; directly. Test it by running &lt;code&gt;[].valueOf()&lt;/code&gt; in your browser's console. The result of this operation will be &lt;code&gt;[]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, we still have &lt;code&gt;[]&lt;/code&gt; which is not a primitive value, so method &lt;code&gt;toString()&lt;/code&gt; gets called. Test it by running &lt;code&gt;[].toString()&lt;/code&gt; in your browser's console. Returned value is &lt;code&gt;''&lt;/code&gt; which is a primitive value. With this, conversion of &lt;code&gt;Object&lt;/code&gt; to primitive value is finally completed.&lt;/p&gt;

&lt;p&gt;But, look closely, operands still have different types, &lt;code&gt;x&lt;/code&gt; is now &lt;code&gt;''&lt;/code&gt; which is type &lt;code&gt;String&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; is still &lt;code&gt;0&lt;/code&gt; which is type &lt;code&gt;Number&lt;/code&gt;. Conversion must continue.&lt;/p&gt;

&lt;p&gt;Now, &lt;code&gt;x&lt;/code&gt; will be converted to &lt;code&gt;Number&lt;/code&gt;. We already know, from previous examples, that &lt;code&gt;''&lt;/code&gt; is going to be &lt;code&gt;0&lt;/code&gt; after conversion. When conversion is completed operands will be compared by value. Since values are the same, &lt;code&gt;0&lt;/code&gt; is indeed equal to &lt;code&gt;0&lt;/code&gt;, result will be &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 06
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;             &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operand &lt;code&gt;x&lt;/code&gt; is type of &lt;code&gt;Object&lt;/code&gt;, but operand &lt;code&gt;y&lt;/code&gt; is type of &lt;code&gt;String&lt;/code&gt;. Operand &lt;code&gt;x&lt;/code&gt;, with value &lt;code&gt;[]&lt;/code&gt;, will be converted to primitive value. We already know, from Sample 05, the result of this conversion is going to be empty string &lt;code&gt;''&lt;/code&gt;. After conversion, operand &lt;code&gt;x&lt;/code&gt; will have value &lt;code&gt;''&lt;/code&gt; and type &lt;code&gt;String&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since both operands are now the same type, &lt;code&gt;String&lt;/code&gt;, conversion is completed. When compared by value, &lt;code&gt;''&lt;/code&gt; is not the same as &lt;code&gt;'0'&lt;/code&gt;, so this comparison is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 07
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&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="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a,b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;   &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operand &lt;code&gt;x&lt;/code&gt; is type of &lt;code&gt;Object&lt;/code&gt; and operand &lt;code&gt;y&lt;/code&gt; is type of &lt;code&gt;String&lt;/code&gt;. In the conversion step, &lt;code&gt;Object&lt;/code&gt; will be converted to primitive value. &lt;/p&gt;

&lt;p&gt;After conversion, operand &lt;code&gt;x&lt;/code&gt; will have value &lt;code&gt;'a,b'&lt;/code&gt; and type &lt;code&gt;String&lt;/code&gt;. Test it by running &lt;code&gt;['a', 'b'].toString()&lt;/code&gt; in your browser's console.&lt;/p&gt;

&lt;p&gt;Both operands are now types of &lt;code&gt;String&lt;/code&gt;. When compared by value, the result is &lt;code&gt;true&lt;/code&gt;, since values are the same.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 08
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;            &lt;span class="c1"&gt;// Result: false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This one is quite strange and yet simple. Comparing any value with &lt;code&gt;NaN&lt;/code&gt; is always going to result in &lt;code&gt;false&lt;/code&gt;. This is the case even if &lt;code&gt;NaN&lt;/code&gt; is compared to &lt;code&gt;NaN&lt;/code&gt;, which seems quite weird.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sample 09
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n\r\t&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;         &lt;span class="c1"&gt;// Result: true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Operands have different types, so conversion is required. Since the type of &lt;code&gt;x&lt;/code&gt; is &lt;code&gt;String&lt;/code&gt; it will be converted to &lt;code&gt;Number&lt;/code&gt;. After conversion, &lt;code&gt;'\n\r\t'&lt;/code&gt; will be &lt;code&gt;0&lt;/code&gt;. Now, when compared by values, &lt;code&gt;0&lt;/code&gt; is the same as &lt;code&gt;0&lt;/code&gt;, so the result is &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you are wondering how &lt;code&gt;'\n\r\t'&lt;/code&gt;, after conversion, can become &lt;code&gt;0&lt;/code&gt; - it's because of how conversion to &lt;code&gt;Number&lt;/code&gt; works.&lt;/p&gt;

&lt;p&gt;There are some special &lt;a href="https://262.ecma-international.org/#table-string-single-character-escape-sequences" rel="noopener noreferrer"&gt;Single Character Escape Sequences&lt;/a&gt; like &lt;code&gt;\n&lt;/code&gt; (new line), &lt;code&gt;\t&lt;/code&gt; (horizontal tab), &lt;code&gt;\v&lt;/code&gt; (vertical tab), &lt;code&gt;\r&lt;/code&gt; (carriage return) that are always going to be &lt;code&gt;0&lt;/code&gt; when converted to &lt;code&gt;Number&lt;/code&gt;. It does not matter in which order and how many of them are contained inside the same string value.&lt;/p&gt;

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

&lt;p&gt;We all know JavaScript can be weird, but if you look a bit under the hood, things can become much clearer. The same thing is with the Equality &lt;code&gt;==&lt;/code&gt; operator. On the surface it can be really strange, but when you know the algorithm behind it, things can become much easier to understand.&lt;/p&gt;

&lt;p&gt;Either way, I strongly recommend &lt;strong&gt;always using&lt;/strong&gt; the Strict Equality &lt;code&gt;===&lt;/code&gt; operator. But don't get me wrong, it is still really important to know how &lt;code&gt;==&lt;/code&gt; works. It is, after all, a JavaScript feature which is always going to be part of the language.&lt;/p&gt;




&lt;p&gt;Check out other articles on &lt;a href="https://ramomujagic.com/blog/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>emptystring</category>
    </item>
    <item>
      <title>Quick introduction to SSH</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Fri, 18 Nov 2022 20:26:57 +0000</pubDate>
      <link>https://dev.to/rmmgc/quick-introduction-to-ssh-3gmm</link>
      <guid>https://dev.to/rmmgc/quick-introduction-to-ssh-3gmm</guid>
      <description>&lt;p&gt;&lt;em&gt;First of all, you might ask yourself, what is SSH?&lt;/em&gt;&lt;br&gt;
Well, in short, SSH stands for &lt;strong&gt;Secure Shell&lt;/strong&gt;. It allows you to gain, cryptographically secured, command-line (shell) access on a remote machine.&lt;/p&gt;

&lt;p&gt;Remote machine can be your web or build server, or any other machine that can be accessed via SSH.&lt;/p&gt;

&lt;p&gt;On &lt;strong&gt;Linux&lt;/strong&gt; and &lt;strong&gt;macOS&lt;/strong&gt;, command-line SSH client usually comes preinstalled with the system. As such, it can be used directly in the terminal window. For &lt;strong&gt;Windows&lt;/strong&gt;, SSH client is not usually installed with the system, but there are plenty of SSH clients that can be installed manually. In this article, focus will be on macOS.&lt;/p&gt;
&lt;h2&gt;
  
  
  Password based authentication
&lt;/h2&gt;

&lt;p&gt;Establishing an SSH connection is pretty straightforward. But, before it can be done, you need to know &lt;code&gt;username&lt;/code&gt; and &lt;code&gt;hostname&lt;/code&gt;, or &lt;code&gt;IP&lt;/code&gt; address, of the server.&lt;/p&gt;

&lt;p&gt;So basically, you will use the SSH client, on your machine, to connect with the SSH server on the remote machine. Assuming you are on macOS or Linux, you can run the following command to connect via SSH.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &amp;lt;username&amp;gt;@&amp;lt;&lt;span class="nb"&gt;hostname&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;username&lt;/code&gt; - server user.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hostname&lt;/code&gt; - server host. If not known, IP address can be provided instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are connecting with the server for the first time, you will be asked to confirm server identity. If you confirm it, the public key of the server will be saved into your local &lt;code&gt;~/.ssh/known_hosts&lt;/code&gt; file. Next time you try to connect, your &lt;code&gt;known_hosts&lt;/code&gt; file will be checked and since the server public key is already added there, this step will be skipped.&lt;/p&gt;

&lt;p&gt;As a next step, you will be asked for a password to confirm that you are authorized to access the server. If provided password is not correct, connection will be rejected.&lt;/p&gt;

&lt;p&gt;As you might have already noticed, every time you want to establish an SSH connection with the remote machine, you will have to enter a password. This approach is good if you don't access the server frequently, but even so, it is still better to use &lt;strong&gt;SSH keys&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;If you are currently connected via SSH, go ahead and run following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;logout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will terminate the currently running SSH session. Now, let's check out what are those SSH keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  SSH keys basics
&lt;/h2&gt;

&lt;p&gt;SSH protocol uses SSH keys as an access credential. This means that, instead of the password that was used before, you can use SSH keys to connect to the server. Other than that, SSH keys are much more robust, longer and complex than any password could ever be. As such, they are a better and more secure method of authentication.&lt;/p&gt;

&lt;p&gt;SSH uses a pair of keys, public key and private key. They are generated using &lt;a href="https://en.wikipedia.org/wiki/Public-key_cryptography" rel="noopener noreferrer"&gt;public key cryptographic algorithms&lt;/a&gt; and most common of them are &lt;a href="https://en.wikipedia.org/wiki/RSA_(cryptosystem)" rel="noopener noreferrer"&gt;RSA&lt;/a&gt; and &lt;a href="https://en.wikipedia.org/wiki/Digital_Signature_Algorithm" rel="noopener noreferrer"&gt;DSA&lt;/a&gt;. These algorithms are based on a mathematical formula that takes 2 very large prime numbers and outputs public and private key.&lt;/p&gt;

&lt;p&gt;Public key can be shared freely with others, while private key must be saved securely and only the key owner should know its value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Session key
&lt;/h3&gt;

&lt;p&gt;There is one more important key called session key. This key is negotiated by both parties, client and server, during the connection process. Session key is generated using a version of the &lt;a href="https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange" rel="noopener noreferrer"&gt;Diffie-Hellman&lt;/a&gt; algorithm. This algorithm works in a way that both parties contribute equally to the generation of the session key. Because of the nature of the algorithm, the session key represents a shared symmetric key. It means that this key can be used for both encryption and decryption.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication flow
&lt;/h3&gt;

&lt;p&gt;Before a key-based connection can be established, something called &lt;strong&gt;SSH handshake&lt;/strong&gt; is going to happen. SSH cryptographic handshake ensures that both parties, client and server, are authenticated. Below is a sample of communication between client and server during SSH handshake.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnng0br8ngtr66s7akbv1.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%2Fuploads%2Farticles%2Fnng0br8ngtr66s7akbv1.png" alt="Simplified communication overview during SSH cryptographic handshake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Client initializes SSH connection with the server and sends ID of its public key.&lt;/li&gt;
&lt;li&gt;Server checks &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file of the user that the client is attempting to log in.
If a public key with matching ID is found, the server generates a random number and uses the public key to encrypt the message.
Server sends the encrypted message back to the client.&lt;/li&gt;
&lt;li&gt;Client decrypts the number using its private key.&lt;/li&gt;
&lt;li&gt;Client combines decrypted number and shared session key to generate &lt;a href="https://en.wikipedia.org/wiki/MD5" rel="noopener noreferrer"&gt;MD5&lt;/a&gt; hash value.&lt;/li&gt;
&lt;li&gt;Client sends this MD5 hash back to the server as an answer to the encrypted number message.&lt;/li&gt;
&lt;li&gt;Server uses a shared session key and the original number to calculate MD5 hash value.&lt;/li&gt;
&lt;li&gt;Server compares its calculation with the one that the client has sent.&lt;/li&gt;
&lt;li&gt;If two values are matched, it proves that the client has the correct private key.
Client is authenticated and connection is established.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the SSH handshake was successful, connection between client and server will be established. This process is secure since it relies on cryptographic authentication to establish connection between client and server.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating SSH keys
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;By now, you might ask yourself, how can I generate those SSH keys?&lt;/em&gt;&lt;br&gt;
SSH keys can be generated really quickly using following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-b&lt;/span&gt; 4096 &lt;span class="nt"&gt;-C&lt;/span&gt; &amp;lt;email_address&amp;gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &amp;lt;file_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create SSH keys using your the email address as a label. Optionally, you can pass &lt;code&gt;-f&lt;/code&gt; flag where you can specify file name for SSH keys.&lt;br&gt;
If &lt;code&gt;-f&lt;/code&gt; flag is not provided, you will be prompted to provide file name or you can press &lt;code&gt;enter&lt;/code&gt; to accept default. If you press &lt;code&gt;enter&lt;/code&gt;, file name &lt;code&gt;id_rsa&lt;/code&gt; will be used as a default.&lt;/p&gt;

&lt;p&gt;Next, you will be asked to enter a passphrase. If a passphrase is provided, it will be required when ever key is used. This can be useful if someone gains access to the machine where private key is stored, since they will not be able to use private key without correct passphrase.&lt;/p&gt;

&lt;p&gt;When command finishes running, you shold see following files in your &lt;code&gt;~/.ssh&lt;/code&gt; directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;├── &amp;lt;file_name&amp;gt;
├── &amp;lt;file_name&amp;gt;.pub
└── ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File with the extension &lt;code&gt;.pub&lt;/code&gt; contains the data about public key and it can be shared with anyone else. The other file, without &lt;code&gt;.pub&lt;/code&gt; extension, contains the data about private key and it needs to stay secure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enable key-based authentication
&lt;/h2&gt;

&lt;p&gt;To enable key-based authentication with a server, you need to tell the server about your public key. To do so, you need to add your public key to &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file on the server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/&amp;lt;file_name&amp;gt;.pub | pbcopy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will copy your public key to the clipboard. Now, coppied public key needs to be added into the &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file on the server. To do so, login to the server using password authentication.&lt;/p&gt;

&lt;p&gt;Once you gain access to the server, run following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pbpaste &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will paste your, previously copied, SSH key and append it at the end of the content in &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Execute following command to confirm that your public key is saved.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see content of &lt;code&gt;authorized_keys&lt;/code&gt; file printed in terminal window. Your public key should be printed as a last item.&lt;/p&gt;

&lt;p&gt;Now, execute &lt;code&gt;logout&lt;/code&gt; command to terminate current SSH session.&lt;br&gt;
Next time you start a new SSH connection with the same server, authentication will be made using SSH keys.&lt;/p&gt;

&lt;p&gt;This way of authentication is often used on &lt;a href="https://en.wikipedia.org/wiki/CI/CD" rel="noopener noreferrer"&gt;CI/CD&lt;/a&gt; to automate processes and authenticate machines without user interaction.&lt;/p&gt;

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

&lt;p&gt;Today, SSH and SSH keys are incredibly important and used everywhere. From online services to automatically authenticate each other to your Github account to push the code changes.&lt;/p&gt;

&lt;p&gt;You &lt;strong&gt;don't have to be a Secure Shell expert&lt;/strong&gt; by any means, but knowing the basics can come a long way. I hope this post has provided you with just that - the basics.&lt;/p&gt;




&lt;p&gt;This post was first published on &lt;a href="https://ramomujagic.com/blog/quick-introduction-to-ssh/" rel="noopener noreferrer"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ssh</category>
      <category>shel</category>
      <category>macos</category>
      <category>linux</category>
    </item>
    <item>
      <title>React hooks: useMemo</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Fri, 11 Nov 2022 10:54:24 +0000</pubDate>
      <link>https://dev.to/rmmgc/react-hooks-usememo-3o0i</link>
      <guid>https://dev.to/rmmgc/react-hooks-usememo-3o0i</guid>
      <description>&lt;p&gt;If you are working with React, you have probably heard about the term &lt;strong&gt;useMemo&lt;/strong&gt;.&lt;br&gt;
In a nutshell, &lt;code&gt;useMemo&lt;/code&gt; is a built-in React hook that allows you to &lt;strong&gt;memoize output of a function&lt;/strong&gt; to prevent it from re-running on every component re-render.&lt;/p&gt;

&lt;p&gt;So, we could say, the goal of &lt;code&gt;useMemo&lt;/code&gt; hook is to provide a simple way to achieve gains in performance using memoization. But, there is more to it, so let's dive deeper.&lt;/p&gt;
&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;This hook has the following signature.&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;memoizedValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compute&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that &lt;code&gt;useMemo&lt;/code&gt; accepts 2 arguments.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;compute&lt;/code&gt; - function used to compute a result.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;dependencies&lt;/code&gt; - array of dependencies used by &lt;code&gt;compute&lt;/code&gt; function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On the initial render of the component, &lt;code&gt;useMemo&lt;/code&gt; will invoke the &lt;code&gt;compute&lt;/code&gt; function, memoize the result of the &lt;code&gt;compute&lt;/code&gt; function and return the value.&lt;/p&gt;

&lt;p&gt;On every component re-render, &lt;code&gt;userMemo&lt;/code&gt; will check if &lt;code&gt;dependencies&lt;/code&gt; are changed. If change is detected, &lt;code&gt;useMemo&lt;/code&gt; will invoke the &lt;code&gt;compute&lt;/code&gt; function again, otherwise it will return previously memoized value.&lt;/p&gt;




&lt;p&gt;In programming, memoization is usually implemented in a way that memoization function &lt;strong&gt;remembers all inputs&lt;/strong&gt; and results based on those inputs. Next time, when the same inputs are sent to the memoization function, it will return memoized result.&lt;/p&gt;

&lt;p&gt;On the other hand, &lt;strong&gt;useMemo only remembers previous inputs&lt;/strong&gt; and results based on those inputs. As soon as next inputs are not the same as previous inputs, useMemo will run the computation again.&lt;/p&gt;




&lt;h2&gt;
  
  
  When should it be used
&lt;/h2&gt;

&lt;p&gt;Thing is, &lt;code&gt;useMemo&lt;/code&gt; does not give free performance gains. Running &lt;code&gt;useMemo&lt;/code&gt; will consume &lt;strong&gt;CPU time and memory&lt;/strong&gt; which can hurt performance if used incorrectly.&lt;/p&gt;

&lt;p&gt;For this reason, &lt;code&gt;useMemo&lt;/code&gt; should not be used everywhere whenever possible, but rather in some situations where memoization would provide performance benefits.&lt;/p&gt;

&lt;p&gt;Overall, make sure that your component does not depend on &lt;code&gt;useMemo&lt;/code&gt; at all. Only if you notice performance issues, introduce &lt;code&gt;useMemo&lt;/code&gt;. Here are some questions you can ask yourself to decide if &lt;code&gt;useMemo&lt;/code&gt; should be used.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Is the component running expensive calculations?&lt;/li&gt;
&lt;li&gt;Is the component re-rendering often?&lt;/li&gt;
&lt;li&gt;Is the component doing data transformation?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is no guideline which will tell you when exactly to use this hook. You need to make sure that you understand the problem you are having and then, you will know if &lt;code&gt;useMemo&lt;/code&gt; can help you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show me some code
&lt;/h2&gt;

&lt;p&gt;It is true that usage of &lt;code&gt;useMemo&lt;/code&gt; hook may vary and depend on your component, but it is still possible to provide some examples where &lt;code&gt;useMemo&lt;/code&gt; would make sense and where not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad case
&lt;/h3&gt;

&lt;p&gt;As the first example, let's say we want to calculate user age based on the year of birth and the current year. While at it, you might want to add &lt;code&gt;useMemo&lt;/code&gt; there, you know, just in case.&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;userAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;currentYear&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;yearOfBirth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;currentYear&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yearOfBirth&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;Well, there you go, this is a bad usage of the &lt;code&gt;useMemo&lt;/code&gt; hook. Computers are fast and doing simple calculations like this will take basically no time. Just do the following instead.&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;userAge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentYear&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;yearOfBirth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;When doing calculations on primitive values like numbers, strings, booleans, never wrap them with useMemo. It can &lt;strong&gt;take longer&lt;/strong&gt; to execute useMemo than the calculation itself.&lt;/p&gt;




&lt;h3&gt;
  
  
  Good case
&lt;/h3&gt;

&lt;p&gt;In this example, there is a function that takes an array of users and formats the activities for every user. Additionally, alongside activities, we want to return users' full name and age.&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;activitiesPerUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&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;return&lt;/span&gt; &lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;user&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;fullName&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&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="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;activities&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;formatUserActivities&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This function might take a lot of time if formatting of activities is complicated or if the &lt;code&gt;users&lt;/code&gt; array is large. In this case, it makes sense to wrap the function in the &lt;code&gt;useMemo&lt;/code&gt; hook, especially if the component gets re-rendered multiple times with the same &lt;code&gt;users&lt;/code&gt; object.&lt;/p&gt;




&lt;p&gt;Memoize results of functions that are doing &lt;strong&gt;expensive calculations and data transformations&lt;/strong&gt;. Even if component is not being re-rendered at all, it is still good to wrap those functions with useMemo.&lt;/p&gt;




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

&lt;p&gt;Oh, congrats, you made it to the end. I hope that the &lt;code&gt;useMemo&lt;/code&gt; hook is not as complicated anymore.&lt;/p&gt;

&lt;p&gt;From my experience, it is always worth memoizing computed non-primitive values, like arrays or objects, that are passed down to the child components. It is even more important if the parent component hosts state variables that are frequently changed. This can prevent unnecessary re-renders of child components.&lt;/p&gt;

&lt;p&gt;In general, do not think about performance optimization too much. If your application is not performant, don't worry, you will notice it.&lt;/p&gt;




&lt;p&gt;This post was first published on &lt;a href="https://ramomujagic.com/blog/react-hooks-usememo/"&gt;my blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>hooks</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Configuring macOS command line</title>
      <dc:creator>Ramo Mujagic</dc:creator>
      <pubDate>Mon, 07 Nov 2022 12:57:44 +0000</pubDate>
      <link>https://dev.to/rmmgc/configuring-macos-command-line-2490</link>
      <guid>https://dev.to/rmmgc/configuring-macos-command-line-2490</guid>
      <description>&lt;p&gt;If you are serious about doing any kind of development work, it is really important to have an easy to use command line interface. Out of the box, macOS comes with the Terminal app. We will start from there and try to improve overall experience.&lt;/p&gt;

&lt;p&gt;Before taking a deeper dive, take a look at the image below to get a glimpse of what is going to be covered here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hk8epsEZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3otf1062hfyyft1rknq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hk8epsEZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3otf1062hfyyft1rknq2.png" alt="Terminal app - configured terminal window" width="880" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There will be plenty of things that can be changed and you can end up with completely different interface, if you choose so.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shell setup
&lt;/h2&gt;

&lt;p&gt;Before going any further, you need to choose which shell to use. There are many out there and macOS usually comes with two of them pre-installed, &lt;code&gt;bash&lt;/code&gt; and &lt;code&gt;zsh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;My choice here is &lt;code&gt;zsh&lt;/code&gt;. It is highly customisable and comes with many &lt;a href="https://github.com/hmml/awesome-zsh"&gt;powerful features&lt;/a&gt;. Even if you currently use &lt;code&gt;bash&lt;/code&gt;, switching to &lt;code&gt;zsh&lt;/code&gt; is quite simple. More so, &lt;code&gt;zsh&lt;/code&gt; is an extended version of &lt;code&gt;bash&lt;/code&gt;. They basically share a lot of common functionality and features.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Zsh
&lt;/h3&gt;

&lt;p&gt;Majority of macOS versions already come with &lt;code&gt;zsh&lt;/code&gt; pre-installed. To check if &lt;code&gt;zsh&lt;/code&gt; is installed on your system, run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;zsh &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you have &lt;code&gt;zsh&lt;/code&gt; installed, it's version should be printed out. In this case, you do not need to do any additional changes.&lt;/p&gt;

&lt;p&gt;However, if &lt;code&gt;zsh&lt;/code&gt; is not installed, you can easily install it using &lt;code&gt;homebrew&lt;/code&gt;. Homebrew is a macOS package manager that makes it easy to install missing software. It usually comes pre-installed on many macOS versions. To install &lt;code&gt;zsh&lt;/code&gt; using &lt;code&gt;homebrew&lt;/code&gt;, run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;zsh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can confirm if it's installed by running the &lt;code&gt;zsh --version&lt;/code&gt; command again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zsh as a default shell
&lt;/h3&gt;

&lt;p&gt;Depending on the macOS version, your default shell might be set to &lt;code&gt;bash&lt;/code&gt;. You can easily check it by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see that the output is &lt;code&gt;zsh&lt;/code&gt;, then your default shell is already set properly. In case you need to set &lt;code&gt;zsh&lt;/code&gt; as a default shell, do so by running the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;chsh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;which zsh&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, start new shell session (close the current and open a new Terminal window), for the changes to take effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrate from bash
&lt;/h3&gt;

&lt;p&gt;If you are coming from &lt;code&gt;bash&lt;/code&gt;, you might have some custom configuration saved in your &lt;code&gt;.bash_profile&lt;/code&gt; or &lt;code&gt;.bashrc&lt;/code&gt; files. Since those files are &lt;code&gt;bash&lt;/code&gt; specific, they will not be used by &lt;code&gt;zsh&lt;/code&gt; and all configuration saved in them must be migrated into &lt;a href="https://zsh.sourceforge.io/Intro/intro_3.html"&gt;zsh specific files&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.zshenv&lt;/code&gt; is sourced on all shell invocations. Here you should save all exports that are needed for other programs.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.zshrc&lt;/code&gt; is sourced when running in interactive shells. Here you can put all configs that make the shell experience more enjoyable, like: &lt;em&gt;aliases&lt;/em&gt;, &lt;em&gt;functions&lt;/em&gt;, &lt;em&gt;options&lt;/em&gt;, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make sure that all of your &lt;code&gt;$PATH&lt;/code&gt; exports are saved in the &lt;code&gt;.zshenv&lt;/code&gt; file, since it will be sourced on every shell invocation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Oh My Zsh framework
&lt;/h2&gt;

&lt;p&gt;When you switch to &lt;code&gt;zsh&lt;/code&gt;, installing &lt;a href="https://ohmyz.sh/"&gt;Oh My Zsh&lt;/a&gt; is one single thing that you must do. This will make your shell really awesome!&lt;/p&gt;

&lt;p&gt;Oh My Zsh is a community driven framework for managing &lt;code&gt;zsh&lt;/code&gt; configuration. Installing it could not be simpler, just run the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Oh My Zsh install command assumes that you already have &lt;strong&gt;git installed&lt;/strong&gt; on your machine. In case you don't, follow &lt;a href="https://git-scm.com/book/en/v2/Getting-Started-Installing-Git"&gt;this guide&lt;/a&gt; to install it.&lt;/p&gt;

&lt;p&gt;Oh My Zsh will save it's configuration into the &lt;code&gt;~/.zshrc&lt;/code&gt; file. In case you already had &lt;code&gt;.zshrc&lt;/code&gt; created before, it's content will be copied and saved in &lt;code&gt;~/.zshrc.pre-oh-my-zsh&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;You can move your previous configuration back to the &lt;code&gt;~/.zshrc&lt;/code&gt; by copying it from &lt;code&gt;~/.zshrc.pre-oh-my-zsh&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is usually a good idea to create &lt;code&gt;~/env.sh&lt;/code&gt; where you can keep your custom configuration. Then in &lt;code&gt;~/.zshrc&lt;/code&gt; you can use the &lt;code&gt;source&lt;/code&gt; command to load it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...

&lt;span class="c"&gt;# Load evn.sh file&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; ~/env.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that your custom configuration will always be sourced when running shell in interactive mode. When you need to add or change custom configuration, just do it in the &lt;code&gt;env.sh&lt;/code&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Themes
&lt;/h3&gt;

&lt;p&gt;Your shell might be powerfull now, but it is not good enough if it looks ugly. Luckily, setting a theme with Oh My Zsh is a quite simple.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;~/.zshrc&lt;/code&gt; file in your favorite editor, &lt;code&gt;vim&lt;/code&gt; of course. In there, you will find a variable with the name &lt;code&gt;ZSH_THEME&lt;/code&gt;. By default, it will be set to &lt;code&gt;robbyrussel&lt;/code&gt;. To change the theme, just provide a different theme name.&lt;/p&gt;

&lt;p&gt;There are tons of already pre-made &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Themes"&gt;themes&lt;/a&gt; available to pick from.&lt;/p&gt;

&lt;p&gt;Personally, I use the &lt;code&gt;arrow&lt;/code&gt; theme since it provides simple, minimal and clean interface. To enable the &lt;code&gt;arrow&lt;/code&gt; theme just set &lt;code&gt;ZSH_THEME="arrow"&lt;/code&gt; in your &lt;code&gt;~/.zshrc&lt;/code&gt; file. Make sure to restart your shell session after.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...

&lt;span class="c"&gt;# Set name of the theme to load --- if set to "random", it will&lt;/span&gt;
&lt;span class="c"&gt;# load a random theme each time oh-my-zsh is loaded, in which case,&lt;/span&gt;
&lt;span class="c"&gt;# to know which specific one was loaded, run: echo $RANDOM_THEME&lt;/span&gt;
&lt;span class="c"&gt;# See https://github.com/ohmyzsh/ohmyzsh/wiki/Themes&lt;/span&gt;
&lt;span class="nv"&gt;ZSH_THEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arrow"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You can also use &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/External-themes"&gt;external themes&lt;/a&gt; which are created by the community. Using external themes requires more work since they need to be added to the custom theme directory. You can follow &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/Customization#overriding-and-adding-themes"&gt;this guide&lt;/a&gt; for more information about this topic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;Great thing about Oh My Zsh is that it &lt;strong&gt;comes bundled&lt;/strong&gt; with all &lt;a href="https://github.com/ohmyzsh/ohmyzsh/wiki/plugins"&gt;kinds of plugins&lt;/a&gt;. This allows you to easily extend the functionality of your shell, just by enabling them. Plugins can be easily enabled in the &lt;code&gt;~/.zshrc&lt;/code&gt; file by changing the &lt;code&gt;plugins&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;One such bundled plugin is called &lt;code&gt;web-search&lt;/code&gt;. It allows you to query popular services, like google, from your terminal window. To enable this plugin, just add &lt;code&gt;web-search&lt;/code&gt; to the &lt;code&gt;plugins&lt;/code&gt; variable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...

&lt;span class="c"&gt;# Which plugins would you like to load?&lt;/span&gt;
&lt;span class="c"&gt;# Standard plugins can be found in $ZSH/plugins/&lt;/span&gt;
&lt;span class="c"&gt;# Custom plugins may be added to $ZSH_CUSTOM/plugins/&lt;/span&gt;
&lt;span class="c"&gt;# Example format: plugins=(rails git textmate ruby lighthouse)&lt;/span&gt;
&lt;span class="c"&gt;# Add wisely, as too many plugins slow down shell startup.&lt;/span&gt;
&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;web-search&lt;span class="o"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Keep in mind that &lt;code&gt;plugins&lt;/code&gt; variable is actually an array. If you have multiple values inside, they must be separated with empty space.&lt;/p&gt;

&lt;p&gt;Now, let's switch to &lt;strong&gt;third party plugins&lt;/strong&gt;, since there are so many good ones. To use third party plugins you need to install them into the &lt;code&gt;$ZSH_CUSTOM/plugins&lt;/code&gt; directory. After that, the only thing that needs to be done is to add the plugin, by it' name, into the &lt;code&gt;plugins&lt;/code&gt; variable.&lt;/p&gt;

&lt;p&gt;I would recommend installing following plugins since they can increase your shell productivity significantly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;zsh-autosuggestions&lt;/code&gt; - suggests commands as you type based on history and completions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;zsh-syntax-highlighting&lt;/code&gt; - highlights commands while you type them in the interactive terminal.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Install &lt;code&gt;zsh-autosuggestions&lt;/code&gt; running following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-autosuggestions &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-autosuggestions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;code&gt;zsh-syntax-highlighting&lt;/code&gt; running following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/zsh-users/zsh-syntax-highlighting.git &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ZSH_CUSTOM&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="p"&gt;~/.oh-my-zsh/custom&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;/plugins/zsh-syntax-highlighting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When plugins are installed, enable them via &lt;code&gt;plugins&lt;/code&gt; variable and restart your shell for effects to take place.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;...

&lt;span class="c"&gt;# Which plugins would you like to load?&lt;/span&gt;
&lt;span class="c"&gt;# Standard plugins can be found in $ZSH/plugins/&lt;/span&gt;
&lt;span class="c"&gt;# Custom plugins may be added to $ZSH_CUSTOM/plugins/&lt;/span&gt;
&lt;span class="c"&gt;# Example format: plugins=(rails git textmate ruby lighthouse)&lt;/span&gt;
&lt;span class="c"&gt;# Add wisely, as too many plugins slow down shell startup.&lt;/span&gt;
&lt;span class="nv"&gt;plugins&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;web-search zsh-autosuggestions zsh-syntax-highlighting&lt;span class="o"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Plugins can provide a lot of value and extend your shell in so many ways, but there is also one downside. Every plugin you add will &lt;strong&gt;impact shell performance&lt;/strong&gt; and &lt;strong&gt;startup time&lt;/strong&gt;. So, choose plugins wisely and keep only the ones you are actually using.&lt;/p&gt;

&lt;h2&gt;
  
  
  Terminal app
&lt;/h2&gt;

&lt;p&gt;This section is all about configuring, default, Terminal app that come preinstalled on every macOS.&lt;/p&gt;

&lt;p&gt;You might wonder, why not use more feature rich apps like &lt;a href="https://iterm2.com/"&gt;iTerm2&lt;/a&gt;?&lt;br&gt;
The reason for me is really simple, I just do not use much of the provided features and the benefits for me are not that big.&lt;/p&gt;

&lt;p&gt;With that out of the way, let's configure the Terminal app.&lt;/p&gt;
&lt;h3&gt;
  
  
  Install Fira Code font
&lt;/h3&gt;

&lt;p&gt;I have tried a lot of fonts in the terminal environment, but this one just feels the best. It is a completely free, monospaced font, containing &lt;a href="https://github.com/tonsky/FiraCode#fira-code-free-monospaced-font-with-programming-ligatures"&gt;ligatures&lt;/a&gt; for common programming multi-character combinations.&lt;/p&gt;

&lt;p&gt;Fastest way to install the font is to go to the &lt;a href="https://github.com/tonsky/FiraCode/releases"&gt;releases page&lt;/a&gt; of the Fira Code repository and download the latest version. Once downloaded, you can just install all fonts provided in the &lt;code&gt;ttf&lt;/code&gt; directory. With that done, Fira Code is installed onto your system.&lt;/p&gt;
&lt;h3&gt;
  
  
  Custom profile
&lt;/h3&gt;

&lt;p&gt;In the Terminal app, profiles can define custom configuration and behavior. To modify customization to our liking, a custom profile needs to be created.&lt;/p&gt;

&lt;p&gt;It is totally fine to customize it manually, but there are also a lot of third party themes that can be used in the Terminal app. One example is the &lt;a href="https://github.com/dracula/terminal-app"&gt;Dracula theme&lt;/a&gt;. Usually, third party themes will be provided via &lt;code&gt;.terminal&lt;/code&gt; file which can be imported in the Terminal app.&lt;/p&gt;

&lt;p&gt;I personally use the Dracula theme myself. You can download &lt;code&gt;.zip&lt;/code&gt; from &lt;a href="https://draculatheme.com/terminal"&gt;official website&lt;/a&gt;. It should come with the &lt;code&gt;Dracula.terminal&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;To install it, open the Terminal app and go to &lt;em&gt;Preferences &amp;gt; Profiles&lt;/em&gt;. From there, click on the &lt;em&gt;More&lt;/em&gt; icon and a dropdown will be shown where you need to select &lt;em&gt;Import&lt;/em&gt;. When the theme is imported, it will be saved as a new profile with the name &lt;code&gt;Dracula&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Make sure that &lt;code&gt;Dracula&lt;/code&gt; profile is selected. On the bottom, you should see the &lt;em&gt;Default&lt;/em&gt; button. Click on the button and it will set, currently selected, profile as default. With this, when the new Terminal window is open, it will automatically use selected profile.&lt;/p&gt;

&lt;p&gt;On the right side, you can see all the settings that can be changed. Since we use the Dracula theme, most of the settings does not need to be changed, but I like to tweak some of the options to make it more nice.&lt;/p&gt;

&lt;p&gt;Let's start with &lt;strong&gt;Background&lt;/strong&gt; settings. Click on the &lt;em&gt;Background icon&lt;/em&gt; and a new window should open. Here you can configure Terminal background settings. I like to keep it simple, so for me, settings are set to following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Background color   black (#000000)
Opacity            90%
Blur               5%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will give you a Terminal window that is slightly transparent with a blurred background. I like it since it looks clean and opacity is high enough so underlying windows are not visible that much.&lt;/p&gt;

&lt;p&gt;Next, the &lt;strong&gt;Font&lt;/strong&gt; needs to be changed. Click on the &lt;em&gt;Change&lt;/em&gt; button under the &lt;em&gt;Font&lt;/em&gt; section and the new window should open. Select &lt;strong&gt;Fira Code&lt;/strong&gt; as your font and adjust settings to your linking.&lt;/p&gt;

&lt;p&gt;You can also tweak other settings as well, but I do not change them since they are defined by the Dracula theme anyways.&lt;/p&gt;

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

&lt;p&gt;Some people find working with terminal and command line tools very hard and often are trying to avoid it completely. But the truth is, &lt;strong&gt;it is inevitable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When things are like that, why don't we make sure that the command line environment looks nice and actually help us to increase our productivity?&lt;/p&gt;

&lt;p&gt;By choosing the right terminal app, changing shell and tweaking theme configuration it is possible to enhance command line experience drastically. I really hope that this post has given you a glimpse into what is possible and, at the end, you are able to customize your command line environment to your liking.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>shell</category>
      <category>zsh</category>
      <category>ohmyzsh</category>
    </item>
  </channel>
</rss>
