<?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: Kai</title>
    <description>The latest articles on DEV Community by Kai (@odddev).</description>
    <link>https://dev.to/odddev</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%2F113570%2Fefe3dbf1-3d10-4520-9f07-84adba86d020.jpg</url>
      <title>DEV Community: Kai</title>
      <link>https://dev.to/odddev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/odddev"/>
    <language>en</language>
    <item>
      <title>How to Know Whether to Use Data URLs</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sat, 24 Feb 2024 14:49:43 +0000</pubDate>
      <link>https://dev.to/odddev/how-to-know-whether-to-use-data-urls-59ng</link>
      <guid>https://dev.to/odddev/how-to-know-whether-to-use-data-urls-59ng</guid>
      <description>&lt;p&gt;We often can provide assets with a URI or a so-called “Data URL” on the web. As they are so straightforward to use, they get pretty often copied (from a tutorial, snippet, or whatnot) without us being able to tell what they do, when to prefer them, or whether you should still be using them altogether. It's one of the lesser-known performance tweaks I will shed some light on in this blog post.&lt;/p&gt;

&lt;p&gt;This post was reviewed by &lt;a href="https://github.com/acme"&gt;Leon Brocard&lt;/a&gt; &amp;amp; &lt;a href="https://activenode.de/"&gt;David Lorenz&lt;/a&gt;. Thank you! ❤️&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Data URLs Anyway
&lt;/h2&gt;

&lt;p&gt;First things first, what are we talking about here? Let's make a simple example of a background image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;


div {
  height: 100px;
  width: 100px;
  background-image: url('https://placehold.co/600x400');
}

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

&lt;/div&gt;



&lt;p&gt;That snippet is quite simple. We add a div and configure it to hold a background image. You might know that there is a second approach to this, however. This approach makes use of a so-called “data URL”:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;div {
  height: 100px;
  width: 100px;
  background-image: url('data:image/svg+xml;charset=utf-8;base64,PHN2ZyB4bWxucz0iaHR0cDovL(...)TEwLjRaIi8+PC9zdmc+');
}

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

&lt;/div&gt;



&lt;p&gt;Now, that is different. The two snippets output the same result. However, in the latter, we provide the image data directly in the CSS instead of requesting it from a server. Here, we provide the encoded image binary data directly in a given convention. There is no need to catch it from the server, as we provide the file in CSS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A new URL scheme, “data”, is defined. It allows inclusion of small data items as “immediate” data, as if it had been included externally.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Base64 Encoding
&lt;/h3&gt;

&lt;p&gt;How does this work? The image data is encoded with an algorithm called “Base64”. It sounds a bit complicated, but it's, in fact, not. The main goal of such encodings is to display binary data in Unicode. That's why such are called “binary to text encodings.” A digit in Base64 can represent a maximum of 6 bits. Why is that? Let's make an example. We want to display &lt;code&gt;101101&lt;/code&gt; as text. But hold on a second. Did you recognize something? &lt;em&gt;We already did it!&lt;/em&gt; Writing out &lt;code&gt;101101&lt;/code&gt; made a bit-sequence apparent to you as a reader. _We encoded binary to text._Now, let's imagine instead of “0” and “1”, we decide for “A” and “B”: &lt;code&gt;BABBAB&lt;/code&gt;. Guess what? We have just Base &lt;strong&gt;2&lt;/strong&gt; encoded data! Yay. Do you see the issue here? We must utilize eight &lt;strong&gt;bytes&lt;/strong&gt; of data to encode six &lt;strong&gt;bits&lt;/strong&gt; of data, as A and B in ASCII take up one byte. We “inflate” or bloat this data by ~1067% (100 % / 6 bit * 64 bit).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary Sequence&lt;/th&gt;
&lt;th&gt;Base2 Encoded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101101&lt;/td&gt;
&lt;td&gt;BABBAB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;To tackle this problem, there is a little trick: we add more characters to encode a bigger binary sequence at once. Let's make another example here: Base4 encoding.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary Sequence&lt;/th&gt;
&lt;th&gt;Base4 Encoded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;00&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;01&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101101&lt;/td&gt;
&lt;td&gt;CDB&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;How would our sequence of &lt;code&gt;101101&lt;/code&gt; look with that algorithm? It encodes to &lt;code&gt;CDB&lt;/code&gt;. This results in a far smaller bloat of only 400%! We continue in that manner until we have 64 distinct characters representing a specific sequence each. That's what Base64 encoding is.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Binary Sequence&lt;/th&gt;
&lt;th&gt;Base64 Encoded&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;000000&lt;/td&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;000001&lt;/td&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;011001&lt;/td&gt;
&lt;td&gt;Z&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;011010&lt;/td&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;101101&lt;/td&gt;
&lt;td&gt;t&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;111111&lt;/td&gt;
&lt;td&gt;/&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In the given table, we see that our example sequence of &lt;code&gt;101101&lt;/code&gt; is encoded by only using the character &lt;code&gt;t.&lt;/code&gt; That means we only add two more bits to display 6 bits of data!  That is merely an inflation of roughly 133%. Awesome! Well, but why stop there? Why did we expressly agree on “6 bits” and not use, e.g., Base128 encoding? ASCII has enough characters, right? However, 32 of them are control characters that computers may interpret. That would lead to severe bugs. Why this is exactly is out of the scope of this blog post (I mean, the Base64 algorithm already kinda is). Just so much: There is a Base91 and Base85 encoding; however, as illustrated in our examples above, “power of two” is more readily encoded when it comes to byte data, and that's why we mostly settled on that.&lt;/p&gt;

&lt;p&gt;To summarize this a little, let's say we want to encode 10 bytes of data, which is 80 bits. That means we need 14 characters (80/6≈14) to represent that. The binary sequence &lt;code&gt;000000&lt;/code&gt; is represented as ASCII &lt;code&gt;A&lt;/code&gt; in Base64. Read this: “The binary data of my image has six consecutive zeros somewhere. The algorithm of Base64 encoding will transform this into 'A.'” In ASCII, &lt;code&gt;A&lt;/code&gt; is eight bits long. Represented in binary, it looks like this: 01000001. Thus, we made this sequence two bits larger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preamble
&lt;/h2&gt;

&lt;p&gt;As always, when it comes to performance, it's complex. There are a lot of layers to the question of whether to use a data URL or not. It heavily depends on how your external resources are hosted. Are they hosted on the edge? What's the latency? The same goes for the hardware of the users. How long does it take for them to decode the given data? May this take even longer than requesting the already decoded resource? You must always collect RUM data and compare approaches to know best. However, generally speaking, we could say that there is a sweet spot where the Base64 encoding overhead exceeds the overhead of an HTTP request, and thus, it's advisable not to use Data URLs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Premise
&lt;/h2&gt;

&lt;p&gt;Let's repeat this: if the overhead of a request to an external resource exceeds the size of the Base64 extra bloat, you should use a data-url. We are not talking about the payload here. It's just what the request in isolation costs us. Do we have a bigger &lt;strong&gt;total size&lt;/strong&gt; with Base64 encoding or an HTTP request? Let's make an example here. We start with a white pixel. We decode this as PNG in, well, the resolution 1x1. We will add other background colors throughout this blog post. The following table already yields the most important values: uncompressed file size as PNG, the (bloated) size when Base64 is encoded, the total request size (headers and payload), and finally, the total size of the data-URL.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resolution&lt;/th&gt;
&lt;th&gt;Background Color&lt;/th&gt;
&lt;th&gt;Size&lt;/th&gt;
&lt;th&gt;Base64 Encoded Size&lt;/th&gt;
&lt;th&gt;Request Size (total)&lt;/th&gt;
&lt;th&gt;Data URL Size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1x1&lt;/td&gt;
&lt;td&gt;White&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;864&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;In this first example, we would need to transfer 721 (864 – 143) more bytes if we did &lt;strong&gt;not&lt;/strong&gt; utilize a data URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure the Request
&lt;/h2&gt;

&lt;p&gt;Before we head deeper into data points and their analysis, I want to clarify how we measure the total size of a request. How do we get the value in the “Request Size (total)” column? The most straightforward way is to head to the network tab in the Web Developer Tools. The first thing you do is create a snapshot of all the page's network requests. Then, find the one for the particular media in question.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hweIqJde--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/VhL5ZPkI.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hweIqJde--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/VhL5ZPkI.png" alt='A screenshot of web developer tools. The network tab is active. A particular network request of an image is highlighted and selected. A filter "images" is set. Three numbers emphasize the user journey: number one is on the network tab, number two is on the "images" filter, and number three is on the highlighted network request of an image.' width="800" height="390"&gt;&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;{
    "Status": "200OK",
    "Version": "HTTP/2",
    "Transferred": "22.12 kB (21.63 kB size)",
    "Referrer Policy": "strict-origin-when-cross-origin",
    "Request Priority": "Low",
    "DNS Resolution": "System"
}

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

&lt;/div&gt;



&lt;p&gt;Now, you might think it's pretty easy, right? Subtract the payload (21.63 kB) from the transferred data (21.63 kB) and done. However, you also have to take the request header into account! That adds a little something.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NSuqTEcz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/qN2TccQH.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NSuqTEcz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/qN2TccQH.png" alt='A screenshot from a network request as captured by Firefox Developer Tools. It features two important tabs: "Response Headers" and "Request Headers."' width="689" height="1011"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Long story short: in the screenshot above, we see both headers, request and response. This data is the “overhead” we need to take into consideration. Everything else is payload – not bloated by Base64 encoding.&lt;/p&gt;

&lt;h2&gt;
  
  
  To the Lab!
&lt;/h2&gt;

&lt;p&gt;Now, equipped with that knowledge and skills, we can create some data points. I did this with a Node.js script. It creates many images and writes their file sizes and Base64 encoded sizes in a CSV file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import sharp from "sharp";
import fs from "fs";

// Create a new direcotry for that run
const nowMs = Date.now();
const outputDirectory = `./out/${nowMs}`;
fs.mkdirSync(outputDirectory);

// Create a CSV file in that directory
const csvWriter = fs.createWriteStream(`${outputDirectory}/_data.csv`, {
  flags: 'a'
});

// Write the table column labels
csvWriter.write('color,resolution,fileSize,base64size \n');

// Create 700 images for each color in the given list
["white", "red", "blue", "green", "lavender"].forEach(async (color) =&amp;gt; {
  for (let index = 1; index &amp;lt;= 700; index++) {
    const image = await createImage(color, index, index, outputDirectory);
    // Write the data into CSV file
    csvWriter.write(`${color},${index},${image.sizeByteLength},${image.sizeBase64} \n`);
  }
});

async function createImage(color, width, height, outputDirectory) {
  const imageBuffer = await sharp({
    create: {
      width,
      height,
      channels: 3,
      background: color
    }
  }).png().toBuffer();
  const fileName = `${width}x${height}.png`;
  fs.writeFileSync(`${outputDirectory}/${fileName}`, imageBuffer);

  return {
    outputDirectory,
    fileName,
    // This is where we unwrap the relevant sizes and return them
    sizeByteLength: imageBuffer.byteLength,
    sizeBase64: imageBuffer.toString('base64url').length
  }
}

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

&lt;/div&gt;



&lt;p&gt;Okay, this might seem a bit excessive (and it might be), but it generates 700 images with different resolutions (from 1x1 to 700x700) for five different background colors. It then writes the file size and the Base64 encoded size into a file that can be imported into a spreadsheet.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Data
&lt;/h3&gt;

&lt;p&gt;Let us analyze the data a bit, starting with the raw results. Just so that we know what we are &lt;em&gt;basically&lt;/em&gt; looking at.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;color&lt;/th&gt;
&lt;th&gt;resolution&lt;/th&gt;
&lt;th&gt;fileSize&lt;/th&gt;
&lt;th&gt;base64size&lt;/th&gt;
&lt;th&gt;requestSize&lt;/th&gt;
&lt;th&gt;Data-url size&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;blue&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;864&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;blue&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;124&lt;/td&gt;
&lt;td&gt;867&lt;/td&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;blue&lt;/td&gt;
&lt;td&gt;699&lt;/td&gt;
&lt;td&gt;8592&lt;/td&gt;
&lt;td&gt;11456&lt;/td&gt;
&lt;td&gt;9366&lt;/td&gt;
&lt;td&gt;11479&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;blue&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;8606&lt;/td&gt;
&lt;td&gt;11475&lt;/td&gt;
&lt;td&gt;9380&lt;/td&gt;
&lt;td&gt;11498&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;green&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;864&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;green&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;124&lt;/td&gt;
&lt;td&gt;867&lt;/td&gt;
&lt;td&gt;147&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lavender&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;9218&lt;/td&gt;
&lt;td&gt;12291&lt;/td&gt;
&lt;td&gt;9992&lt;/td&gt;
&lt;td&gt;12314&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;red&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;864&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;red&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;8606&lt;/td&gt;
&lt;td&gt;11475&lt;/td&gt;
&lt;td&gt;9380&lt;/td&gt;
&lt;td&gt;11498&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;white&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;864&lt;/td&gt;
&lt;td&gt;143&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;td&gt;...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;white&lt;/td&gt;
&lt;td&gt;700&lt;/td&gt;
&lt;td&gt;2992&lt;/td&gt;
&lt;td&gt;3990&lt;/td&gt;
&lt;td&gt;3766&lt;/td&gt;
&lt;td&gt;4013&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;We have data points for 700 PNG images for five colors: blue, green, red, lavender, and white. The essential part is within the columns “fileSize” and “base64size”. These are the (uncompressed) file size and the size when we Base64 encode the same file. These data points are followed by columns referring to the total sizes. Column “requestSize” stands for the size of the payload plus the headers (request and response). In reality, they will differ a bit from request to request. Here, I assumed a static value of 774 bytes, more or less the median in Firefox. That's good enough for the analysis. The same goes for the data URL size. We want to add 23 bytes, as the encoded string is prefixed by &lt;code&gt;data:image/png;base64,&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Findings
&lt;/h3&gt;

&lt;p&gt;Interestingly, more than one data point may cross the line of 100% bloat. It's the line where the sizes would be exactly equal. That means that there may be cases where it would have been finally better not to use a data-URL, to be the other way around again right afterward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j-68fFlX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/BfWIcR2I.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j-68fFlX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/BfWIcR2I.png" alt="A diagram that shows how the 'bloat' data points evolve. The bloat is the size of the Base64 encrypted image to the basic file size. It's a line diagram with a data series for each color: white, blue, green, red, and lavender. The 100% line is highlighted. It's noticeable how they cross this line in a stackering motion once. But white crosses it two times." width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's understand the basic chart first. What does this mean? Simply put, for lavender, red, green, and blue, it would be preferable to use data-url up to a resolution of about 340x340. For white, you must start asking questions from a resolution of 570x570. Let's dig deeper into it. You can recognize a few things. First of all, the more complex (in our case, 'lavender') an image is, the more it gets bloated, thus reaching the point of “request preference” faster. That makes sense, as the PNG encoding needs to yield more uncompressable value. The next thing to notice is how the three base colors (Red, Green, and Blue) behave more or less identically. This makes sense because their binary data looks more or less the same. Of course, the most remarkable is the white data series. Not only is it the least complex image, thus the one that's longest in the “use data-url sector,” but it's also crossing the 100% bloat line twice! Well, the most critical data points are the ones where we cross the line of 100% bloat, right? Let's have a look at this then:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;resolution&lt;/th&gt;
&lt;th&gt;blue&lt;/th&gt;
&lt;th&gt;green&lt;/th&gt;
&lt;th&gt;lavender&lt;/th&gt;
&lt;th&gt;red&lt;/th&gt;
&lt;th&gt;white&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;337&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.9993&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;339&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;1.0013&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;341&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.9997&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;343&lt;/td&gt;
&lt;td&gt;0.9997&lt;/td&gt;
&lt;td&gt;0.9997&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.9997&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;573&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.9997&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;602&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;1.0287&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;608&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;0.9936&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2k5_TU5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/9ncE3Jr7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2k5_TU5D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/9ncE3Jr7.png" alt="A diagram illustrating where the different color data series cross the 100% bloat line. Lavender tips over at a resolution of 337 and goes above 100% at 339 again, to fall below the threshold again at 341. The point of falling beneath 100% is identical to 343 for blue, green, and red. White falls under 100% at 573, climbs above 100% again at 602, and is eventually lower than 100 at 608." width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Woah! Even the lavender-series does the “crossing the line twice move”! Outstanding. Okay, what do these data points mean?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For blue, red, and green, using a data URL for resolutions up to 343x343 would be preferable&lt;/li&gt;
&lt;li&gt;Lavender has different sections:

&lt;ul&gt;
&lt;li&gt;337 and 338: A request is preferable&lt;/li&gt;
&lt;li&gt;339 and 340: A data URL is preferable (again)&lt;/li&gt;
&lt;li&gt;341 and bigger: A request is preferable&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;As already said, white also has different sections that stretch over a greater delta:

&lt;ul&gt;
&lt;li&gt;573 to 601: A request is preferable&lt;/li&gt;
&lt;li&gt;602 to 607: A data URL is preferable (again)&lt;/li&gt;
&lt;li&gt;608 and bigger: A request is preferable&lt;/li&gt;
&lt;/ul&gt;


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

&lt;blockquote&gt;
&lt;p&gt;⚠️ Just a heads up again: this is merely a lab. It is there to showcase how to measure and compare your data. It is not 100% accurate for the field, as we assumed static sizes that may differ from request to request. This is especially relevant for the lavender series, where the conclusion might change from one probe to the next. Also, it would help if you did not draw general conclusions from here. Depending on the complexity and file format, the results are entirely different. See how lavender is already far more different from white. That means that the edge cases are not to be generalized.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  To the Field!
&lt;/h2&gt;

&lt;p&gt;Now, let's examine a real example. There is a great website hosted at &lt;a href="https://www.ungra.dev/"&gt;https://www.ungra.dev/&lt;/a&gt;. We load one optimized image there. It's as good as it gets for a JPG. The image has 21.63 kB, which adds up to 22.57 kB with the header overhead.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8arsbumd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/C1mawWek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8arsbumd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/C1mawWek.png" alt='A screenshot of the network information of an HTTP request. It transferred a picture. Three values are highlighted: "Transferred 22.12 kB (21.63 kB size)", "Response Header (492 B)", "Request Header (452 B)".' width="599" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I refrain from posting the Base64 encoded version here. It's huge. It has a solid of 28,840 characters. Thus, the Data URL is 28,2 kB large. All in all, using &lt;strong&gt;a Data URL would transfer 5,751 bytes more.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, that image is only 239 × 340 pixels large. You can see that the evaluation depends more on the complexity of the image than its sheer resolution.&lt;/p&gt;

&lt;h2&gt;
  
  
  File Formats
&lt;/h2&gt;

&lt;p&gt;You may wonder about file formats. I tried to see how far I could go with the image in question from the previous chapter and converted it to AVIF. I compressed it – with reasonable losses - to 3,9 kB! That sounds promising to come to an even more apparent conclusion this time, right? However, the same picture also only has 5,2 kB Base64 encoded. That means that, in general terms, the question of whether to use a Data URL is not significantly impacted by the file format. It just scales the numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Excurse: What's with non-binary data?
&lt;/h2&gt;

&lt;p&gt;Something that is probably interesting here is what happens with non-binary data. Let's take SVGs, for example. How are they Base64 encoded, and what does that mean for our decision to put them into data URLs or not? You can, of course, Base64 encode them just as any other data. However, it generally doesn't make sense, as the original file is already available in Unicode. Remember, Base64 is a “binary to text encoding” algorithm! If you encode SVGs, you don't win anything but bloat the file.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ There are some edge cases where this might come in handy! In general terms, however, refrain from doing this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;However, you can still use Data URIs for SVGs and the like! It's just that you do not add &lt;code&gt;charset=utf-8;base64&lt;/code&gt; to it. It's merely &lt;code&gt;data:image/svg+xml;utf8,&amp;lt;SVG&amp;gt;...&lt;/code&gt;. Remember that such a URL does not need to be Base64 encoded. We need this extra step to render binary data.&lt;/p&gt;

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

&lt;p&gt;Now that you know how to get the relevant numbers, it's relatively easy to conclude. Again, you must compare the request overhead with the increased file size of the Base64 encoded media. Is the request header size, response header size, and payload bigger than the Base64 data URL string? If yes, use the latter. If not, make a request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other Considerations
&lt;/h2&gt;

&lt;p&gt;In reality, you have to take a few more considerations into account. However, as they are very individual for particular scenarios or concern other “layers,” I will only briefly mention them here.&lt;/p&gt;

&lt;h3&gt;
  
  
  Media Processing
&lt;/h3&gt;

&lt;p&gt;First, if your media is not hosted on the edge, the latency increase may not be worth it. Also, the other way around: if your web app runs on really (!) poor hardware, it might not be worth using a data-url.&lt;/p&gt;

&lt;h3&gt;
  
  
  Compare Zipped Data
&lt;/h3&gt;

&lt;p&gt;Your data should be compressed. If you haven't done so yet, do it now (there is a big chance you do this already, as it's pretty much the default for most hosters/servers/...). This also means that we need to compare the compressed data here. (What we didn't do throughout this post to keep things simple.) The same goes for optimizing your resources first. For images, compress them as much as possible and use modern file formats like AVIF or WebP. SVGs should also be minimized with tools like OMGSVG.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP/2 and Server Push
&lt;/h3&gt;

&lt;p&gt;With HTTP/2, a concept called server push makes data URLs nearly obsolete! A server can provide the resources we have encoded inline in one go. Read more about that here: &lt;a href="https://web.dev/performance-http2/#server-push"&gt;https://web.dev/performance-http2/#server-push&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Unfortunately, &lt;strong&gt;server push is mainly abandoned and deprecated&lt;/strong&gt; nowadays. Even to an extent where I can say ignore it. If you want to read more about the why, head to this article: &lt;a href="https://developer.chrome.com/blog/removing-push/"&gt;https://developer.chrome.com/blog/removing-push/&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;Data URIs are primarily used with binary data encoded with an algorithm called Base64. It is made to display binary data in a text-based way. This is excellent for Data URIs, for they are text-based! However, Base64 makes the data larger. That means you must check whether it's better to have overhead with the request or to bloat your file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.smashingmagazine.com/2017/04/guide-http2-server-push/"&gt;https://www.smashingmagazine.com/2017/04/guide-http2-server-push/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/"&gt;https://www.davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/web/http/basics_of_http/data_urls"&gt;https://developer.mozilla.org/en-US/docs/web/http/basics_of_http/data_urls&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/performance-http2/"&gt;https://web.dev/performance-http2/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.rfc-editor.org/rfc/rfc2397#section-2"&gt;https://www.rfc-editor.org/rfc/rfc2397#section-2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Base64"&gt;https://developer.mozilla.org/en-US/docs/Glossary/Base64&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/probably-dont-base64-svg/"&gt;https://css-tricks.com/probably-dont-base64-svg/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://css-tricks.com/lodge/svg/09-svg-data-uris/"&gt;https://css-tricks.com/lodge/svg/09-svg-data-uris/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.chrome.com/blog/removing-push/"&gt;https://developer.chrome.com/blog/removing-push/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Confluence - a List of Recurring Posts</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Wed, 24 May 2023 17:38:27 +0000</pubDate>
      <link>https://dev.to/odddev/confluence-a-list-of-recurring-posts-akm</link>
      <guid>https://dev.to/odddev/confluence-a-list-of-recurring-posts-akm</guid>
      <description>&lt;p&gt;One of my most controversial opinions is that I have a soft spot for Confluence. But wait, let me explain it a bit further. I understand all the pain people have with it. I get it. I'm usually in the same boat. &lt;em&gt;However&lt;/em&gt;, I do not think it's Atlassian's fault for providing a better UX. For many things, it is just administrated and used poorly! Or, to put it in simpler terms, Confluence needs to be utilized correctly. I do not want to discuss this further in this post, but I want to provide an excellent example of what you can do with Confluence. This already implicitly covers my main (opinionated) arguments for my stance on the discussion.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Use-Case
&lt;/h2&gt;

&lt;p&gt;One of the most common things people want to do in Confluence is to have a list of recurring posts. Picture meeting notes, workshops, etc. Usually, they have these requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a structured template for a post&lt;/li&gt;
&lt;li&gt;an overview of the posts&lt;/li&gt;
&lt;li&gt;a complete/detailed post&lt;/li&gt;
&lt;li&gt;having that data searchable&lt;/li&gt;
&lt;li&gt;good UX to add another item&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What we want is a list of notes that share the same structure. For example, all of them should serve an agenda, a date, a list of participants, and so on. They should be organized in a structured overview to be easily scanned and searched.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problems
&lt;/h2&gt;

&lt;p&gt;I discovered that many teams (or even organizations) struggle to have a good concept for this everyday use case. The problems are often the same:&lt;/p&gt;

&lt;h3&gt;
  
  
  Bad UX of Adding a New Entry
&lt;/h3&gt;

&lt;p&gt;That's probably the most annoying issue. The concept of adding a new entry is quite often to copy a portion of the page. This comes with various problems: It's unclear what to copy, formatting issues are cloned, copying on a slow page (and such page &lt;em&gt;is&lt;/em&gt; getting bloated, thus slow over time) is cumbersome, specific formats are cluttered and need to be manually fixed, etc. Wouldn't having a “Add Entry” button be nice instead?&lt;/p&gt;

&lt;h3&gt;
  
  
  No Overview
&lt;/h3&gt;

&lt;p&gt;It usually gets confusing when all the entries are pushed into one page. The information is all over the place, you can't keep track, it's hard to find and filter entries, the page gets slow, and the structure is not visible from the page tree. It's also hard to distinguish between general and detailed information. Latter is not necessarily needed prominently in the list, yet you have no choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Clear Blueprint
&lt;/h3&gt;

&lt;p&gt;Having a blueprint with mandatory information is relatively easy to maintain initially. People commonly add a table with respectively labeled columns. However, as the lists progress, columns might get removed, renamed, added, formatted differently, interpreted, copied with flaws, and so on. The needed information more and more get ambiguous. And the lower the quality of the entries, the more people feel demotivated to maintain the same in the upcoming items. Do you also have a list with missing and low-quality data in the rows? Didn't that list start out pretty ambitious and well-thought-out, only to be neglected after a while?&lt;/p&gt;

&lt;h2&gt;
  
  
  Making it Work
&lt;/h2&gt;

&lt;p&gt;Now comes the fun part. We solve these issues in an exquisite and convenient way. We use custom templates, the table of contents feature, the excerpt macro, task lists, and a button to add a new child page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding a Template
&lt;/h3&gt;

&lt;p&gt;The first thing we need is a template. That's basically a prefilled page representing our recurring document. Let's stick with meeting notes for our example.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ Info&lt;br&gt;&lt;br&gt;
Explanation on how to exactly add a template is beyond the scope of this post and varies heavily between the different Confluence versions. However, you can always head to the &lt;a href="https://confluence.atlassian.com/doc/create-a-template-296093779.html"&gt;official Atlassian documentation&lt;/a&gt; and read about it there.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;First of all, you need to know these things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What information is needed on the blog post as a whole?&lt;/li&gt;
&lt;li&gt;What information is known upfront or mandatory?&lt;/li&gt;
&lt;li&gt;What information is needed in an overview?&lt;/li&gt;
&lt;li&gt;The basic outline and layout of your post.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on this, you can create your post template. What we do now is create a blank template. First, we are going to add variables to the page. To do so, open the add macro dialog (macros are called slash commands in the newest versions) and choose “New Variable.” Do this for every mandatory information that can not be automatically (computational) evaluated, and the author knows upfront. Let's say, for example, the time and date the meeting will take place. Don't overthink it at this point. Our template can be further optimized and adapted as time moves on. All we have to do now is further build (or set up) the post template. Add the needed sections, fields, placeholders, headlines, and whatnot. Follow along with the &lt;a href="https://confluence.atlassian.com/doc/create-a-template-296093779.html"&gt;official documentation&lt;/a&gt; in case you need help—attention to the “Instructional Text” and “Template Variables” chapters. There is one last step you need to do now: add an excerpt! To do so, choose the excerpt macro (or slash command) and add it. Now place everything into the box needed for a basic post overview. Commonly you'd refer to this as “header data.” For meeting notes, it can be, for example, the date of the meeting, participants, agenda, etc. Only add a little. Be very cautious not to overload the excerpt. Further information and a detailed guide are here: &lt;a href="https://confluence.atlassian.com/doc/excerpt-macro-148062.html"&gt;https://confluence.atlassian.com/doc/excerpt-macro-148062.html&lt;/a&gt;. The idea is that we, later on, show this exact excerpt in the overview. This can be easily done with a specific macro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t3v1ze1_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/xDcQpZoC.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t3v1ze1_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/xDcQpZoC.png" alt="A screenshot showing an example template. It showcases the usage of the excerpt, variable, and placeholder macros." width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ First Confluence Pitfall:&lt;/strong&gt; Do not restrict users from adding templates! They are a crucial part of the app and are meant to be dynamically used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Adding a Parent Page
&lt;/h3&gt;

&lt;p&gt;Now we want to have a parent page. Think of this more as a “folder” than really a page. The difference to a directory as we know it from operating systems is that it's quite feature-rich. We can provide any content we want, including an overview of child pages! That's precisely what we do now. First, add some meta information to your page. Let's say a title: “Meeting Notes of Foobar!”. You can do whatever you want and need. Add a header image, disclaimer, intro, or whatever. Now comes the critical part: the child-page macro. Add it where you want to have the overview of past meetings and configure it like so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excerpt Display: Rich Text&lt;/li&gt;
&lt;li&gt;Heading Style: Something that suits your document, but the second level should do the trick, usually&lt;/li&gt;
&lt;li&gt;Sort Children by: Creation&lt;/li&gt;
&lt;li&gt;Optional – Number of Children: Normally, you want to restrict the child pages displayed For meeting notes, it's often a good idea to set this to three. It would show the currently open notes, the preceding meeting, and one additional for reference.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More usage information here: &lt;a href="https://confluence.atlassian.com/doc/children-display-macro-139501.html"&gt;https://confluence.atlassian.com/doc/children-display-macro-139501.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mention the “Exceprt Display” option. This is where you tell the macro to show the page excerpts. Remember how we added it to the template? The option “Rich Text” shows the content precisely like on the page (otherwise, it would be transformed into a text-only version).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Second Confluence Pitfall:&lt;/strong&gt; Pages are directories, not documents! Please do not use them as you would with a word processor (or whatever is used to create a content-complete PDF eventually). Generally, it would help if you strived to have many pages with little content. The same goes for spaces. There is no one fits all solution, but often spaces are defined far too broadly.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, now you should have a list of child pages that, more or less, looks like you'd have added their excerpt content to the just added page. You can try this out by adding a few example pages (they don't necessarily have to be created from the template from the first chapter). Now we need one additional thing. Add the macro “Create from Template.” We use it to have a button to create a child page, so a meeting note. Configure it like so:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Button Text: Set this to your needs, e.g., “Add Meeting Note”&lt;/li&gt;
&lt;li&gt;Template Name: The Template you have created in the first chapter&lt;/li&gt;
&lt;li&gt;Title of the Page to be Created: Set this to your needs (be aware that you can use variables here), e.g., “Meeting – @spaceName on @currentDate”&lt;/li&gt;
&lt;li&gt;Space Key: the key of the current space (usually defaults to that already)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;More usage information here: &lt;a href="https://support.atlassian.com/confluence-cloud/docs/insert-the-create-from-template-macro/"&gt;https://support.atlassian.com/confluence-cloud/docs/insert-the-create-from-template-macro/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PAB8e9Pc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/eZVIEgRX.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PAB8e9Pc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.snap.as/eZVIEgRX.png" alt="A screenshot showing an example overview page. It showcases the usage of the child display and the create from template button." width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Third Confluence Pitfall:&lt;/strong&gt; Don't consider Confluence to be a document silo. It's not Google Drive. Try to utilize dynamic tools and macros as much as possible. Try to use it as a no-code front-end platform rather than a document management system.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Bonus – Task List
&lt;/h4&gt;

&lt;p&gt;If you plan to keep track of the pages' tasks, you may also consider adding the &lt;a href="https://support.atlassian.com/confluence-cloud/docs/insert-the-task-report-macro/"&gt;task report macro&lt;/a&gt;. It lists all the tasks on a particular page and its child pages. In our case, that would be our newly created parent page.&lt;/p&gt;

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

&lt;p&gt;With this approach, you have an easy way for users to add a new post with a given format. You have a very easy-to-scan archive of posts and keep the overview performant. It mitigates the problems we addressed in this post. You may want to read through them again now. Please also take this opportunity to rethink how you utilize the tools you have within Confluence! Get creative. 😊 The features are meant to be used!&lt;/p&gt;

</description>
      <category>confluence</category>
      <category>tip</category>
      <category>tutorial</category>
      <category>documentation</category>
    </item>
    <item>
      <title>Why I don't Use Odd.af Anymore</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sat, 25 Feb 2023 19:53:34 +0000</pubDate>
      <link>https://dev.to/odddev/why-i-dont-use-oddaf-anymore-181a</link>
      <guid>https://dev.to/odddev/why-i-dont-use-oddaf-anymore-181a</guid>
      <description>&lt;p&gt;The last few days, I have been pretty busy migrating my domain from “odd.af” to “ungra.dev”. I posted a bit on Social Media about the story, but I wanted to wrap it up in detail in this blog post.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Happened
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ The top-level domain “AF” is Afghanistan's country code top-level domain. A country that the &lt;a href="https://en.wikipedia.org/wiki/Afghanistan?oldformat=true#Second_Taliban_era_(2021%E2%80%93present)" rel="noopener noreferrer"&gt;Taliban took over in 2021&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A few weeks ago, my domain provider, Vercel, wrote me that my domain will not be able to be renewed. It's due for auto-renewal on the 22nd of April. They stated they have issues with the authorities in Afghanistan.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Due to factors that are out of Vercel’s control, we are no longer able to accept or renew .AF registrations, similarly to most registries today. CcTLDs (country-code Top Level Domains), like .AF, are managed by bureaus from the country, sovereign states, or dependent territory. An attempt to register a ccTLD will open a series of requests to the managing entity. We have made this decision due to the uncertainty Afghanistan continues to have with an evolving political situation. The .AF registry has been unresponsive and payments to them have not been possible, disrupting process renewals and new registrations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, long story short, the Tailban did not create a bureau being able to handle domain registry. I'm, however, still not sure whether this means every single domain provider is in the same boat and all “.AF” domains will expire sooner or later. On one hand, it sounds like this. On the other hand, this would be huge. Like, imagine not holding a silly domain for private use but for a big company with its HQ in Afgahnistan.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I had to do
&lt;/h2&gt;

&lt;p&gt;Vercel recommended I get a new domain ready.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We recommend you prepare another domain and are here to help you with that process.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To be honest, at first, I thought about talking to other providers in order to keep “odd.af”. I love that domain and didn't want to go through the pain of migration. The longer I slept about it, the clearer it was that I had to move away. I had several good reasons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason One: The Expiry
&lt;/h3&gt;

&lt;p&gt;Well, that one is easy. Since my domain cannot be renewed, I have to do something. A possible solution to the problem is to ditch it and use another.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reason Two: Language Barrier
&lt;/h3&gt;

&lt;p&gt;A problem I always had with “odd.af” was that it was hardly understood in Germany. Not only was it a different language, but you also needed to know basic “internet slang”. Especially for older folks, it was quite confusing. Admittedly it was rather short and very easy to spell out. Also, not that I really cared, but many people are not keen on profanity in – at least somewhat – professional domains.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ “af” is an internet acronym for “as fuck”. The domain meant “odd as fuck”.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Reason Three: Uncertainty of CcTLDs
&lt;/h3&gt;

&lt;p&gt;The first reason I didn't like to use a ccTLD anymore was simply that it was semantically incorrect. I have nothing to do with Afgahnistan, especially because AF is not a ccTLD with a “Commercial License”. Such &lt;a href="https://en.wikipedia.org/wiki/Country_code_top-level_domains_with_commercial_licenses?oldformat=true" rel="noopener noreferrer"&gt;domains&lt;/a&gt; (e.g., “me”, “am”, “fm”, “sh”) adopt policies to be not reliant on the infrastructure of a country. For example, “.co” is not managed by the Colombian Government but rather a Colombian and US company. The second reason is, well, that it's a ccTLD, thus dependent on the particular country. 😊 What happened to my domain is seldom enough but can happen anytime. I don't want to have this unnecessary risk anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I did
&lt;/h2&gt;

&lt;p&gt;At first, I gathered a list of potential domain names. &lt;a href="https://media2.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%2F0umc60hcq9tpsam5q5hx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0umc60hcq9tpsam5q5hx.png" alt="A screenshot of a note-taking app. The headline is Domains and it is followed by a list of potential domain names that are odd.dev, odd.am, oddest.me, odddev.codes, iodd.dev, iodd.de, odd.zone, ungera.de, odd.law, oddi.am, ungra.de" width="153" height="380"&gt;&lt;/a&gt;The problem was to find one that had not a ccTLD (see previous chapter), was affordable, and was not too boring. I pretty much liked the idea of translating “odd” to German. Among others, it means “ungerade” or “ungrade”. Then “ungra.de” came to my mind. However, first of all, that domain was already taken, and second, it &lt;em&gt;still&lt;/em&gt; relies on a ccTLD. (I mean, “DE” would've been not too bad since I'm a resident of Germany, but well.) Finally, I went with “ungra.dev” it's a portmanteau of “ungrade” (German for “odd”) and “dev. I pretty much like it, and it's only 15 $ per year.&lt;/p&gt;

&lt;p&gt;Now came the hard part: migrating. It was a bit easier than I initially thought to be honest, but still pretty much painful. At first, I went through all accounts using an “odd.af” mail address. I just filtered for “odd.af” in my password manager. Surprisingly, they were very few since I use masked e-mails for most of my credentials.&lt;/p&gt;

&lt;p&gt;After I changed all the addresses in these accounts (not to my new “ungra.dev”, but rather “masked e-mails”), I went on and checked my mail account. I informed everyone I had contact with that my mail address changed.&lt;/p&gt;

&lt;p&gt;Then I updated all the links on my social media profiles and my website. Nothing should point to “odd.af” anymore.&lt;/p&gt;

&lt;p&gt;The last step was to redirect the old domain to the new endpoints technically. In most cases, this was just a case of adding “ungra.dev” to the project and installing a 301 (“moved permanently”) redirect to the “odd.af” domain. One redirect was a bit more complicated. It was blog.odd.af. I changed the custom domain configuration in write.as, but I can only provide one, meaning I needed to create a redirect at Vercel. This is also surprisingly inelegant, as you have to create a &lt;a href="https://github.com/OddDev/blog.odd.af/blob/main/vercel.json" rel="noopener noreferrer"&gt;repository with a certain configuration file&lt;/a&gt; and then assign the “to be redirected” domain to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "redirects": [
        { "source": "/", "destination": "https://blog.ungra.dev/" }
    ]
}

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

&lt;/div&gt;



&lt;p&gt;Or in other words, I needed to create a nearly empty project and assign “blog.odd.af” to it. I found &lt;a href="https://blog.ali.dev/posts/how-to-do-subdomain-url-redirects-with-vercel-hosting/" rel="noopener noreferrer"&gt;this blog post&lt;/a&gt; explaining this approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Done
&lt;/h2&gt;

&lt;p&gt;I'm so glad that I'm through with this truly unnecessary workload. It's super hard to find the time and energy to do this. It's quite a relief that I think I have it off the plate. Keep your fingers crossed that I didn't forget about anything. 🤞&lt;/p&gt;

</description>
      <category>php</category>
      <category>packaging</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How to Fix Faulty Spotify Icon in KDE Plasma Application Switch</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Wed, 14 Dec 2022 09:30:56 +0000</pubDate>
      <link>https://dev.to/odddev/how-to-fix-faulty-spotify-icon-in-kde-plasma-application-switch-5efj</link>
      <guid>https://dev.to/odddev/how-to-fix-faulty-spotify-icon-in-kde-plasma-application-switch-5efj</guid>
      <description>&lt;h2&gt;
  
  
  Cover image description
&lt;/h2&gt;

&lt;p&gt;A screenshot showing an application switch with three open apps: system settings, Spotify and Firefox. The icon of the Spotify entry is highlighted and clearly wrong. Only the label "Spotify" gives away, that it's actually the app. The icon is the X11 fallback icon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Applying a KWin Rule
&lt;/h2&gt;

&lt;p&gt;Whether I installed the app image or the Flatpack version of Spotify, I always had issues with the app icon in the window's title bar and the application switch. It fell back to a defaulting x11 icon.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wEkXkMG7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aj61jsbfusxwbyyxyx8t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wEkXkMG7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aj61jsbfusxwbyyxyx8t.png" alt="A screenshot showing an application switch with three open apps: system settings, Spotify and Firefox. The icon of the Spotify entry is highlighted and clearly wrong. Only the label &amp;quot;Spotify&amp;quot; gives away, that it's actually the app. The icon is the X11 fallback icon." width="386" height="200"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MgN5fFo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew8v93cfc3yqk7qkni5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MgN5fFo7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew8v93cfc3yqk7qkni5e.png" alt="A screenshot showing the title bar of Spotify. The title bar features a clearly wrong icon. It's the icon of X11." width="871" height="41"&gt;&lt;/a&gt;&lt;br&gt;
After investigating, it turned out that it's relatively easy to fix. All you need is a simple KWin rule. You don't even need to set any properties with it (at least, I have observed so far). It just needs to be there. For the sake of "better safe than sorry", we add a meaningful property anyway.&lt;br&gt;
Open up "Window Rules" in the "System Settings". Add a new rule and give it a meaningful description. Something like "Spotify" should do the trick. Then add &lt;code&gt;spotify&lt;/code&gt; (lowercase is essential!) as the Window Class. Afterward, click "Add Property" and choose "Desktop file name". Add &lt;code&gt;spotify-client&lt;/code&gt; as the value and select the mode &lt;code&gt;Force&lt;/code&gt;.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ht3f23xa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ie3o5w63jj3k26nu0zzk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ht3f23xa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ie3o5w63jj3k26nu0zzk.png" alt='A screenshot showing the "Window Rules" dialog with the settings as described in the paragraph above.' width="880" height="630"&gt;&lt;/a&gt;&lt;br&gt;
That's it already! Applying the changes should fix the icon.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1N1hb9Wz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfcfubnmiigyxhwed2i9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1N1hb9Wz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mfcfubnmiigyxhwed2i9.png" alt="A screenshot showing the title bar of Spotify and an application switch. Both icons are now correctly displaying the official Spotify app image." width="736" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>plasma</category>
      <category>spotify</category>
      <category>icon</category>
      <category>x11</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 13 - Let's Construct</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Mon, 07 Jun 2021 12:30:10 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-13-let-s-construct-9hb</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-13-let-s-construct-9hb</guid>
      <description>&lt;p&gt;How's tricks? I welcome you to the marvelous world of JavaScript quizzes on Twitter! This very article is part of a series where we deep dive and demystify them. This week is a tough one, so this article is a little longer than usual. So let's jump right into the in-depth exploration of constructors in JavaScript!&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/oliverjumpertz/status/1401137623725445122"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/oliverjumpertz"&gt;Oliver Jumpertz&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;console.log("wth?")&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;This time we have a complex one. However, as confusing as it might seem, it also makes a hell of a lot of fun to destruct.&lt;br&gt;
We start by creating a string. The value of it is pretty essential here, for it's the name of the property we access in the second line two times iteratively. We are accessing the &lt;code&gt;constructor&lt;/code&gt; property of the string. Then we (again) access the property &lt;code&gt;constructor&lt;/code&gt; of the resulting value.&lt;br&gt;
The resulting function gets called with an argument representing a call of a function, &lt;code&gt;console.log("WTH?")&lt;/code&gt;, itself. The return value of that call gets executed (&lt;code&gt;()&lt;/code&gt;) anonymously right after.&lt;br&gt;
So far, so confusing. But worry not, we clear things up right away.&lt;/p&gt;
&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;The output here is probably something the least can guess on the fly. Presumably, the context of the riddle gave it away a bit, tho. It is a log to the console reading "wth?" Well, indeed: what the heck?!&lt;/p&gt;
&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;Let us move through this step by step. First, we get the more accessible things out of the way: accessing object properties by the given string value &lt;code&gt;constructor&lt;/code&gt; twice. Splitting this fraction up in an additional snippet helps to understand what's going on:&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;stringObject&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;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;stringObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="c1"&gt;// Three times the same call:&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;stringObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;stringObject&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="nx"&gt;stringObject&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// foobar&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;stringObject&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test&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;test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// foobar&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;stringObject&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// foobar&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It shows how we can access specific object properties by a string, even if they are part of the string object reference itself. For our Twitter quiz meaning, we are accessing the &lt;code&gt;constructor&lt;/code&gt; property of the string. Then yet again, the property &lt;code&gt;constructor&lt;/code&gt; of the resulting value.&lt;br&gt;
Now comes the crucial part of understanding all of this — the property constructor. What does it hold? Why is it there? Well, it stores the function used to construct the object. Let me explain this concept by another snippet (I'm sorry):&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;FooBar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fooBarInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;FooBar&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;fooBarInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function FooBar()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stringInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// OR new String('foobar')&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;stringInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function String()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we define a custom function used to construct an instance. This instance then holds a property &lt;code&gt;constructor&lt;/code&gt; with the value of the specified function. That's simply what JavaScript automatically does on instantiation.&lt;br&gt;
Further, you can see how this concept works with strings. You use syntactical sugar to avoid writing &lt;code&gt;new String('')&lt;/code&gt;, but the paradigm is the same: a function "String" exists. It accepts an argument, and when called to create an instance, the resulting object has a property &lt;code&gt;constructor&lt;/code&gt; holding the used function. And that's the key-secret here.&lt;br&gt;
Coming back to the original snippet, we create a string and access its property constructor. By now, we know that this property holds the function &lt;code&gt;String&lt;/code&gt;. So what happens if we access the constructor property of a function object? Well, yet again, it holds a function. This time the one used to construct, well, functions themselves. Which is indeed &lt;code&gt;function Function()&lt;/code&gt;.&lt;br&gt;
Let's examine this by another snippet:&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;foo&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;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function Function()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;console.log("something")&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;bar&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// something&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;bar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function Function()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stringInstance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foobar&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// OR new String('foobar')&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;stringInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function String()&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;stringInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// function Function()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mention how a function declaration is just syntactical sugar around &lt;code&gt;new Function()&lt;/code&gt;. So, if the constructor property of a String object is a function, the constructor property of this function is the function used to construct functions, thus the function &lt;code&gt;Function()&lt;/code&gt;. 🤯😂&lt;br&gt;
Now that we have learned this, the rest is pretty straightforward. After accessing the constructor property the second time, we have a function constructing functions. So whatever we pass in as a string gets returned as a function instance. In our case, &lt;code&gt;console.log("wth?")&lt;/code&gt;. Since we do not store this return-value, we call it anonymously immediately right after via &lt;code&gt;()&lt;/code&gt;. And that's how after all of this, &lt;code&gt;console.log("wth?")&lt;/code&gt; gets executed and, well, logs the string &lt;code&gt;wth?&lt;/code&gt; to the console.&lt;br&gt;
Let's wrap it up in one last snippet:&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;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;constructor&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;stringConstructorFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;c&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;stringConstructorFunction&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// function Function()&lt;/span&gt;

&lt;span class="c1"&gt;// As simple as:&lt;/span&gt;
&lt;span class="nb"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;console.log("wth?")&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)();&lt;/span&gt; &lt;span class="c1"&gt;// wth?&lt;/span&gt;
&lt;span class="c1"&gt;// Or in a more common syntax:&lt;/span&gt;
&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wth?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))();&lt;/span&gt; &lt;span class="c1"&gt;// wth?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: the constructor property&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: how constructor functions work in JS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Basics#bracket_notation"&gt;Object Property Bracket Notation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor"&gt;Constructor Property of Object Prototype&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/Function"&gt;Function Constructor&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>constructor</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 12 - Coalesced False</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 02 May 2021 18:23:40 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-12-coalesced-false-3j7</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-12-coalesced-false-3j7</guid>
      <description>&lt;p&gt;S.P.D.S.V.B.E.E.V.! Look who managed to head to dev.to only to find himself reading an article about a tweeted Javascript quiz. In this series, I try to break such down and this week features a lesser-known but often useful operator: Nullish Coalescing!&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/MoradiDavijani/status/1386810656540839938"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/MoradiDavijani"&gt;Hossein Moradi&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This week we have a super quick one. It logs a logical expression to the console. And that's pretty much already it!&lt;br&gt;
The expression itself consists of two parts. The first one compares &lt;code&gt;null&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt;. The result of that is the left-hand side operand of a so-called "Nullish Coalescing Operator" typed as &lt;code&gt;??&lt;/code&gt;. &lt;br&gt;
The right-hand side operand is, again, just &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;The output is also pretty straightforward. At least if you know what a "nullish coalescing operator" does. This expression will log &lt;code&gt;false&lt;/code&gt; to the console.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;For the analysis, we start with the Strict Equal Operator (&lt;code&gt;===&lt;/code&gt;) as it takes higher precedence ("will be evaluated before") than the mysterious two question marks. And it's also reasonably easy. Comparing &lt;code&gt;null&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; will undoubtedly result in &lt;code&gt;false&lt;/code&gt;, won't it? &lt;br&gt;
What's left looks something like: &lt;code&gt;false ?? 1&lt;/code&gt;.&lt;br&gt;
So far, so good, now comes the fun part. A Nullish Coalescing Operator works in its core like a Logical Or (&lt;code&gt;||&lt;/code&gt;). However, instead of checking for falsy values, it only validates for nullish ones! That means either &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;. To get this straight: it will return the left-hand side value if it's not "nullish" or the right-hand side value if not.&lt;br&gt;
And that is the reason &lt;code&gt;false&lt;/code&gt; gets printed to the console. 🥧&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: a not so well known operator in use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: operator precedence and what nullish coalescing operator does&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator"&gt;Nullish Coalescing Operator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence"&gt;Operator Precedence&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>nullish</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 11 - Continue to Break</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 21 Mar 2021 16:29:56 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-11-continue-to-break-5fe6</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-11-continue-to-break-5fe6</guid>
      <description>&lt;p&gt;What up, homeslice? Glad you found this blog series about JavaScript Twitter quizzes! This week is a funny snippet around the loop-manipulating key-words &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt;. Get ready for some serious trickery!&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/FullstackPath/status/1371026592378540032"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/FullstackPath"&gt;fullstack_learning_path&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&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;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;continue&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;i&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;break&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;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippet features a for-loop initializing the variable &lt;code&gt;i&lt;/code&gt; with 1. Said gets incremented by 1 until it's 9 (&lt;code&gt;&amp;lt; 10&lt;/code&gt;). To put it simply: we count from 1 to 9.&lt;br&gt;
In the loop, there are two checks before printing the current index to the console — the first tests whether modulo 3 returns a truthy value, which means everything except 0. In that case, &lt;code&gt;continue&lt;/code&gt; gets executed.&lt;br&gt;
If not, the snippet further validates whether the current index holds 7. In case it does, &lt;code&gt;break&lt;/code&gt; is executed.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;Okay, that one is a bit of a brain-fuck. On first thought, you might conclude it'll log 3 and 6. Since the loop breaks on 7, right? However, it will still also print 3, 6, and 9! All three of the values having no remainder when divided by 3 (&lt;code&gt;% 3&lt;/code&gt;). In case you are still or even more confused, worry not and jump right to the next chapter.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;So, we already figured the loop is counting from 1 to 9. Let's focus on the first check, &lt;code&gt;i % 3&lt;/code&gt;.  It will always be true if it does not result in &lt;code&gt;0&lt;/code&gt;. In case the index can be divided by three without having a remainder, the expression is false. It's true for 1, 2, 4, 5, 7, 8 in this context, to be even more exact.&lt;br&gt;
Let's examine what happens then: &lt;code&gt;continue&lt;/code&gt; is called. This key-word tells the loop to skip the rest of its body and move to the next iteration. Meaning the &lt;code&gt;console.log&lt;/code&gt; at the bottom is never reached. Or the other way around, only 3, 6, and 9 are logged.&lt;br&gt;
Now let's focus on the second if-statement. In case the index holds the value 7, the loop breaks. &lt;code&gt;break&lt;/code&gt; is a key-word telling the loop to stop with everything. It skips the rest of its body and will not iterate further, continuing with whatever is next in the sequence.&lt;br&gt;
That's why this snippet is so funny. It tricks you into believing 9 will not print since it stops after &lt;code&gt;i&lt;/code&gt; reached 7. Well, as we know, this is not the case. And by now, you probably already figured also why. The second statement is, just as &lt;code&gt;console.log(i)&lt;/code&gt;, only reached by 3, 6, and 9. These numbers are not 7 🤯, thus making the body of the second if-statement unreachable code! &lt;code&gt;break&lt;/code&gt; is never executed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: creating logically unreachable-code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: what &lt;code&gt;continue&lt;/code&gt; and &lt;code&gt;break&lt;/code&gt; does&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break"&gt;break&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/continue"&gt;continue&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Remainder"&gt;Remainder Operator (%)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>loops</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 10 - Short &amp;&amp; Circuit &amp;&amp; Evaluation</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 07 Mar 2021 20:40:58 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-10-short-circuit-evaluation-d5f</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-10-short-circuit-evaluation-d5f</guid>
      <description>&lt;p&gt;What's cookin', good lookin'? Welcome to my blog series about demystifying JavaScript quizzes from Twitter! This week is about a rather basic concept. Let's dive right into the beautiful world of logical operators in JavaScript!&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/ravinwashere/status/1366620016293015552"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/ravinwashere"&gt;Ravin&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;name1&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="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ravin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;name4&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rav&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name1&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;name2&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;name3&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;name4&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;username&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we see a declaration of several variables. Or, more precisely, four names. The first one is a seemingly empty string. However, hold in mind that this is not the case! It contains a whitespace symbol. Next, they store &lt;code&gt;undefined&lt;/code&gt;, right followed by another two strings.&lt;br&gt;
The next line is where things get interesting. The previously defined variables are chained with the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; operator, and the output is stored in yet another. They log this last variable, leaving us with the question, what the value of it is.&lt;/p&gt;
&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;If you are not familiar with the presented API, the log might seem to be wildly random. For it is merely &lt;code&gt;undefined&lt;/code&gt;. Isn't it weird how a logical operator does not return a bool? And why does it not take any of the provided strings into account?&lt;/p&gt;
&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;First things first, we need to understand how the &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; in JavaScript works. It returns the first falsy value it encounters or the last (most-right) one. Such value is one of &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, an empty string (&lt;code&gt;""&lt;/code&gt; and such) or &lt;code&gt;undefined&lt;/code&gt;.&lt;br&gt;
This definition may sound a bit weird at first. However, it makes actual total sense (at least in JavaScript terms). Please give it a thought. If everything is truthy, the last expression is returned. This final expression can also be truthy or falsy, then having the sole power to determine the full statement's logical outcome.&lt;br&gt;
Think through these different statements:&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;if&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 string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="c1"&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="kc"&gt;NaN&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="c1"&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="kc"&gt;NaN&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="c1"&gt;//?&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="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="c1"&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="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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="c1"&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a string&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;foo&lt;/span&gt;&lt;span class="dl"&gt;'&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;By now, you should know why the output in the given snippet is &lt;code&gt;undefined&lt;/code&gt;. It's merely the first falsy statement encountered! &lt;code&gt;name1&lt;/code&gt; is a truthy (non-empty!) string, &lt;code&gt;name 2&lt;/code&gt; a falsy undefined. The other two variables aren't even taken into considerations at this point.&lt;br&gt;
Our snippet comes down to:&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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// returning undefined being falsy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This behavior is called "Short-Circuit Evaluation" btw.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The logical AND expression is evaluated left to right, it is tested for possible "short-circuit" evaluation using the following rule:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;(some falsy expression) &amp;amp;&amp;amp; expr&lt;/code&gt; is short-circuit evaluated to the falsy expression;&lt;/p&gt;

&lt;p&gt;Short circuit means that the &lt;code&gt;expr&lt;/code&gt; part above is not evaluated,&lt;/p&gt;

&lt;p&gt;from &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND"&gt;MDN Logical AND (&amp;amp;&amp;amp;)&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: short-circuit evaluation returning the first falsy expression&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: how exactly the Logical AND operator in JavaScript works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_AND"&gt;Logical AND (&amp;amp;&amp;amp;)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#logical_operators"&gt;MDN Expressions and Operators - Logical Operators&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>evaluation</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 9 - Short Read about Length</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 28 Feb 2021 14:55:35 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-9-short-read-about-length-9jn</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-9-short-read-about-length-9jn</guid>
      <description>&lt;p&gt;Wad up? Welcome to my dev.to series about my takes on Twitter code challenges! This time it's going to be awesome. You will learn something about an API you use on a daily basis: length! You read that correctly. &lt;em&gt;Length&lt;/em&gt;. Let's jump right in 👉👉👉&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/apoorv__tyagi/status/1365912115421220865"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/apoorv__tyagi"&gt;Apoorv Tyagi&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&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;100&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;200&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nx"&gt;numbers&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;0&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;numbers&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In that piece of code, they initialize a constant with an array containing two strings - nothing special so far. However, in the next line, the property &lt;code&gt;length&lt;/code&gt; gets overwritten by &lt;code&gt;0&lt;/code&gt;.&lt;br&gt;
Just in case, &lt;code&gt;length&lt;/code&gt; is a property holding the element count of an Array.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The length property of an object which is an instance of type Array sets or returns the number of elements in that array. The value is an unsigned, 32-bit integer that is always numerically greater than the highest index in the array.&lt;/p&gt;

&lt;p&gt;from &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length"&gt;MDN Array.prototype.length&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, so what we do here is replacing the item-count of 2 with a 0.&lt;br&gt;
On the last line, the snippet logs the first element of the array to leave it up for us to guess the output.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;The logged value is not exactly spectacular but may be somewhat counter-intuitive. You probably would expect the length to be read-only or have no significant effect on the calling instance, thus still logging 100.&lt;br&gt;
However, in reality, that's not the case, and it is a tedious matter of &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;That's probably the most boring analysis in the existence of my blogging career yet. Cause the answer is that it's designed like that! The length can be overwritten and ditches any elements on indexes exceeding the given value.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Decreasing the length property does, however, delete elements.&lt;/p&gt;

&lt;p&gt;from &lt;cite&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#relationship_between_length_and_numerical_properties"&gt;MDN Array&lt;/a&gt;&lt;/cite&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In our example, we provide the value of &lt;code&gt;0&lt;/code&gt;. The array is emptied and does not hold a single item anymore. When we call the first index (&lt;code&gt;0&lt;/code&gt;), the value of &lt;code&gt;undefined&lt;/code&gt; reflects precisely that.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: special behavior of overwriting length&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: the length property of an array is not read-only and heavily influences the calling instance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#relationship_between_length_and_numerical_properties"&gt;Relationship between length and numerical properties&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/length"&gt;MDN Array Length Page&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://whereswalden.com/2013/08/05/new-in-firefox-23-the-length-property-of-an-array-can-be-made-non-writable-but-you-shouldnt-do-it/"&gt;New in Firefox 23: the length property of an array can be made non-writable&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>length</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 8 - Timeout!</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 21 Feb 2021 20:03:26 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-8-timeout-1o1</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-8-timeout-1o1</guid>
      <description>&lt;p&gt;Ahoy! Welcome to one of the articles about destructuring a coding quiz from Twitter. This time, we check out a very funny sorting algorithm. Be prepared to order numbers with timeouts!&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/catalinmpit/status/1361617224600064000"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/catalinmpit"&gt;Catalin Pit&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;912&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;39&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&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;num&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;numbers&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="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;num&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The author defines and initializes an array holding a bunch of random numbers. Afterward, we iterate over each of them to set a timer to execute a simple &lt;code&gt;console.log&lt;/code&gt;. Each timer gets executed after so many milliseconds, as the value of the individual array item is.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;No big surprise here. Well, at least if you are familiar with the &lt;code&gt;setTimeout&lt;/code&gt; API and gave the snippet some thought.&lt;br&gt;
Indeed you get a list of sorted integers:&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="mi"&gt;7&lt;/span&gt;

&lt;span class="mi"&gt;11&lt;/span&gt;

&lt;span class="mi"&gt;29&lt;/span&gt;

&lt;span class="mi"&gt;31&lt;/span&gt;

&lt;span class="mi"&gt;39&lt;/span&gt;

&lt;span class="mi"&gt;99&lt;/span&gt;

&lt;span class="mi"&gt;201&lt;/span&gt;

&lt;span class="mi"&gt;912&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;The idea behind this snippet is glorious! Instead of comparing the values and ordering them, you just let time decide. The highest value will delay the callback most, thus be printed last.&lt;/p&gt;

&lt;h1&gt;
  
  
  Appendix
&lt;/h1&gt;

&lt;p&gt;Don't take this snippet seriously! It's meant to be a joke. It would be best if you never utilized &lt;code&gt;setTimeout&lt;/code&gt; like that. It's solely for, well, "setting a timer". Never &lt;em&gt;abuse&lt;/em&gt; this behavior.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: visualising how &lt;code&gt;setTimeout&lt;/code&gt; works&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: &lt;code&gt;setTimeout&lt;/code&gt; is an API to execute a callback after n milliseconds&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout"&gt;WindowOrWorkerGlobalScope.setTimeout()&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>settimeout</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 7 - Even more Evil Eval</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 14 Feb 2021 19:36:33 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-7-even-more-evil-eval-52nh</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-7-even-more-evil-eval-52nh</guid>
      <description>&lt;p&gt;Grüß dich! Welcome to the series about destructuring a JavaScript quiz from Twitter. This Sunday, you'll learn about the &lt;em&gt;one&lt;/em&gt; API you should never use: eval.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/h43z/status/1356614035706380288"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/h43z"&gt;h43z&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// provide an input that makes function challenge call alert(1)&lt;/span&gt;
&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert(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;Here we move into muddy waters. The author declares a function called &lt;code&gt;challenge&lt;/code&gt;, which wraps &lt;code&gt;eval&lt;/code&gt;. The trick is that the argument of the wrapper-function gets piped through &lt;code&gt;.toUpperCase()&lt;/code&gt; first. &lt;br&gt;
The exercise is to make the function execute &lt;code&gt;alert(1)&lt;/code&gt;.&lt;/p&gt;
&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;The output here is not spectacular but feels kind of magic if you do not know what &lt;code&gt;eval&lt;/code&gt; exactly does. However, it is reasonably straightforward: &lt;code&gt;eval&lt;/code&gt; executes whatever piece of code gets passed as a string.&lt;br&gt;
So, for our snippet, the interpreter throws an error since &lt;code&gt;eval&lt;/code&gt; goes and tries to execute "ALERT", which is undefined in the global scope.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReferenceError: ALERT is not defined 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;So, first things first, let's go back to the snippet and examine what exactly happens there. We pass on the argument &lt;code&gt;alert(1)&lt;/code&gt;. In case we would not have a wrapper function,  this piece of code would execute an &lt;code&gt;alert&lt;/code&gt; just fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert(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;However, since it gets piped through &lt;code&gt;.toUpperCase()&lt;/code&gt;, the string, thus the called function, is actually &lt;code&gt;ALERT&lt;/code&gt;, and JavaScript is a case-sensitive language!&lt;br&gt;
Now we need to overcome this issue. I came up with three possible solutions. Let's check them one by one.&lt;/p&gt;
&lt;h2&gt;
  
  
  Altering the Prototype of String
&lt;/h2&gt;

&lt;p&gt;Since the method &lt;code&gt;toUpperCase&lt;/code&gt; is part of the &lt;code&gt;String&lt;/code&gt; prototype, we can easily alter its function body:&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;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&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;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert(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;In that case, when &lt;code&gt;toUpperCase&lt;/code&gt; gets called on &lt;code&gt;input&lt;/code&gt;, it does not pipe and parse the string but instead executes an alert. The called function is just overwritten with the target behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding the function ALERT
&lt;/h2&gt;

&lt;p&gt;We can also go the other way around and add the missing function &lt;code&gt;ALERT&lt;/code&gt; to the global object.&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;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ALERT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert(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;That approach is straight forward. We add another function with the right name. Instead of calling &lt;code&gt;alert&lt;/code&gt;, we call &lt;code&gt;ALERT&lt;/code&gt; instead, which then passes its argument on to &lt;code&gt;alert&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing an Object
&lt;/h2&gt;

&lt;p&gt;The first two solutions were actually illegal. The author explicitly stated to solve the challenge by just passing an input. This is what we do in that approach. We pass an object with the function &lt;code&gt;toUpperCase&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
  &lt;span class="nb"&gt;eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;challenge&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;toUpperCase&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;alert(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;Instead of using the implementation in String's prototype, we pass an object with its own version of &lt;code&gt;toUpperCase&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: how to manipulate an existing function call&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: JavaScript is case-sensitive, &lt;code&gt;eval&lt;/code&gt; executes code from a string (and shouldn't be used!), prototyping &amp;amp; global scope&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval"&gt;Eval&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase"&gt;String Prototype toUpperCase&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://sebhastian.com/is-javascript-case-sensitive/"&gt;JavaScript's case-sensitivity&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/window"&gt;The Window Object&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes"&gt;Prototypes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;strong&gt;Warning&lt;/strong&gt;: Executing JavaScript from a string is an enormous security risk. It is far too easy for a bad actor to run arbitrary code when you use eval(). Read more at &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval!"&gt;MDN&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>eval</category>
    </item>
    <item>
      <title>Destructuring Tweets - Episode 6 - Default Parameter Values</title>
      <dc:creator>Kai</dc:creator>
      <pubDate>Sun, 07 Feb 2021 13:37:57 +0000</pubDate>
      <link>https://dev.to/odddev/destructuring-tweets-episode-6-default-parameter-values-4ab8</link>
      <guid>https://dev.to/odddev/destructuring-tweets-episode-6-default-parameter-values-4ab8</guid>
      <description>&lt;p&gt;Yo! Welcome to the series about destructuring those over-shared JavaScript quizzes on Twitter. Have fun with digging into default values.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet of the Week
&lt;/h1&gt;

&lt;p&gt;This week's &lt;a href="https://twitter.com/agiratech/status/1310503178178359297"&gt;snippet&lt;/a&gt; is from &lt;a href="https://twitter.com/agiratech"&gt;Agira Technologies&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2020&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;evolution&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;defaultYear&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2000&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;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultYear&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;evolution&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="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;year&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first, a variable &lt;code&gt;year&lt;/code&gt; gets declared and initialized with the number 2020. Just to be manipulated in an arrow-function &lt;code&gt;evolution&lt;/code&gt; in the very next line. It accepts a parameter with a default value of 2000. This parameter's value gets assigned to the variable &lt;code&gt;year&lt;/code&gt;. &lt;br&gt;
Now comes the exciting part. The function gets called with &lt;code&gt;null&lt;/code&gt; as the argument, followed by logging the manipulated variable to the console.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Output
&lt;/h1&gt;

&lt;p&gt;You have a relatively high chance of 50 % to guess the output right here. As it's either &lt;code&gt;2000&lt;/code&gt; or &lt;code&gt;null&lt;/code&gt;, right? The initial value of 2020 gets surely overwritten.&lt;br&gt;
However, &lt;code&gt;null&lt;/code&gt; wins. And there is a good reason for that.&lt;/p&gt;

&lt;h1&gt;
  
  
  The Analysis
&lt;/h1&gt;

&lt;p&gt;The reason is that &lt;code&gt;null&lt;/code&gt; is indeed a value. It means the &lt;em&gt;intentional&lt;/em&gt; absence of any other matter. It stands for "nothing" or "void".&lt;br&gt;
That's different with &lt;code&gt;undefined&lt;/code&gt;. Undefined is a primitive type (and a value), meaning that a variable does not have a value assigned.&lt;br&gt;
So, if we leave out an argument in a function call, we do not pass "no value" but rather &lt;code&gt;undefined&lt;/code&gt;.  And that logic is also applied when it comes to default parameters. Only if "no value", so &lt;code&gt;undefined&lt;/code&gt;, is passed, it gets overwritten by the defined default value.&lt;/p&gt;

&lt;h1&gt;
  
  
  Snippet Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trickery&lt;/strong&gt;: When is a default parameter value applied&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Learning&lt;/strong&gt;: Null is indeed a value and therefore a valid argument &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Further Reading&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters"&gt;Default Parameters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null"&gt;null&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined"&gt;undefined&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


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

</description>
      <category>snippet</category>
      <category>javascript</category>
      <category>destructuring</category>
      <category>parameter</category>
    </item>
  </channel>
</rss>
