<?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: Paceaux</title>
    <description>The latest articles on DEV Community by Paceaux (@paceaux).</description>
    <link>https://dev.to/paceaux</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%2F19892%2Fc519f650-5899-4f15-8beb-973cca3d2fb1.jpeg</url>
      <title>DEV Community: Paceaux</title>
      <link>https://dev.to/paceaux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/paceaux"/>
    <language>en</language>
    <item>
      <title>SelectorHound: The tool for Sniffing out CSS Selectors</title>
      <dc:creator>Paceaux</dc:creator>
      <pubDate>Thu, 29 Feb 2024 18:31:48 +0000</pubDate>
      <link>https://dev.to/paceaux/selectorhound-the-tool-for-sniffing-out-css-selectors-18kd</link>
      <guid>https://dev.to/paceaux/selectorhound-the-tool-for-sniffing-out-css-selectors-18kd</guid>
      <description>&lt;p&gt;A few years back I ran into a difficult situation on a project: I needed to find out where a particular CSS selector was used.&lt;/p&gt;

&lt;p&gt;I had a static version of the site, and so I did what any fool might do and I tried searching for it in my IDE. I had two problems though:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Writing a RegEx to essentially &lt;a href="https://stackoverflow.com/a/1732454/1045901"&gt;parse HTML is substantially more &lt;del&gt;difficult&lt;/del&gt; dangerous than you might expect&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The actual live version of the site was managed by a CMS (content management system), and it would be much more difficult to know where that selector might end up&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So after almost a day of failing to produce a good-enough RegEx, I got an idea: What if I just scanned the live site for that selector?&lt;/p&gt;

&lt;p&gt;In about the same amount of hours it took for me to write a RegEx that didn’t always work, I was able to produce a node.js-based script that could scan a live site for the selector.&lt;/p&gt;

&lt;p&gt;So with that, I got the bright idea to make it a proper NPM package that could run on the command line. And now I should introduce you. &lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing SelectorHound
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/selector-hound"&gt;SelectorHound is on NPM &lt;/a&gt;and it’s already at 2.2!&lt;/p&gt;

&lt;p&gt;It’s a Command Line Interface (CLI) that offers a pretty robust set of options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Give it a single selector or a CSS file&lt;/li&gt;
&lt;li&gt;Give it a URL to a sitemap or tell it to crawl your site&lt;/li&gt;
&lt;li&gt;Ask for a lot of details about HTML elements that match the selector, or a screenshot&lt;/li&gt;
&lt;li&gt;Tell it to treat pages like they’re a SPA (Single Page Application) or like static HTML&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What it's good for
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Do you have CSS on your site that you’d like to delete, but you’re uncertain if it’s used anywhere?&lt;/li&gt;
&lt;li&gt;Are you looking for instances where one element may be next to another?&lt;/li&gt;
&lt;li&gt;Would you like to know if your stylesheet has rulesets that could be deleted?&lt;/li&gt;
&lt;li&gt;Has malware infected your CMS and started adding weird links, but you don't know what pages?&lt;/li&gt;
&lt;li&gt;Do you have calls to action that might be missing data attributes?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of these are real world use-cases that I’ve used SelectorHound for. &lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;h3&gt;
  
  
  First, Install it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; selector-hound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For, for more speed (requires installing &lt;a href="https://bun.sh/"&gt;bun&lt;/a&gt; first):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bun &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; selector-hound
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then Run it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;SelectorHound &lt;span class="nt"&gt;-u&lt;/span&gt; https://blog.frankmtaylor.com/sitemap.xml &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="s2"&gt;"h1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Then Look at what you got
&lt;/h3&gt;

&lt;p&gt;First it'll tell you what it's doing as it gets started&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdf3v7e7ea3o8u01jfnfc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdf3v7e7ea3o8u01jfnfc.png" alt="Selector Hound will tell you what the sitemap is, and the CSS selector you've asked for." width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether it's crawling or using your sitemap, it will export the URLs to a JSON file. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;This means you can customize the pages it scans.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And it’ll rely on that JSON file for every scan &lt;em&gt;unless&lt;/em&gt; you pass &lt;code&gt;-X&lt;/code&gt; to force it to generate a new sitemap file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmq0kljutrzfsj6wg3nup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmq0kljutrzfsj6wg3nup.png" alt="SelectorHound tells you how many urls it finds from your sitemap" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;BTW it's way easier to represent fetching with emoji than "I read these URLs from a file on your computer"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Then it’ll tell you when it’s finished and give you a nice summary of what it found. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7utk64c59zunbqdh6oa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7utk64c59zunbqdh6oa.png" alt="SelectorHound tries to tell you everything you might find important like time lapsed, pages scanned, pages with matches, and total results" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can modify the output file name with the &lt;code&gt;-o&lt;/code&gt; flag. Your chosen name will be prepended to &lt;code&gt;pages.json&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't forget to check the log
&lt;/h3&gt;

&lt;p&gt;The log file will look a lot like what you see in the CLI. One big difference though is that any errors that occur will show up here. It'll also tell you in the log if a page didn't have any matches. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwktx3aev1k053c0slfqk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwktx3aev1k053c0slfqk.png" alt="The log file will duplicate messages shown in the CLI but have errors and info logs in between" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  And then check out the results
&lt;/h3&gt;

&lt;p&gt;The results will be in a JSON format. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cf6owxanrf01t9oo0jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cf6owxanrf01t9oo0jt.png" alt="Selector Hound's JSON output includes the URL of the page, the elements that match, and optionally robust details about the element " width="800" height="1065"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;-e&lt;/code&gt; flag can give you details about the elements in case you want to know exactly where on the page your selector is found. &lt;/p&gt;

&lt;p&gt;The output can be pretty robust because it’ll give you results for every page that it found. I am working on a reporting feature that can summarize the results if you don’t want to wade through what could be thousands of lines of JSON. &lt;/p&gt;

&lt;h2&gt;
  
  
  Is it Performant?
&lt;/h2&gt;

&lt;p&gt;It’s faster than writing a RegEx to scan your codebase, that’s for sure.&lt;/p&gt;

&lt;p&gt;I’ve done a some testing and found that, if you were looking for a single HTML element, it might take on average .52s per page. If you install with Bun, you will get maybe a .1s gain.&lt;/p&gt;

&lt;p&gt;We use it a lot at work and I can tell you that one site which has about 5600 pages, SelectorHound takes about 3 hours to find one &lt;em&gt;very&lt;/em&gt; complex CSS selector. If you do the math that's 31 pages a minute or ... &lt;em&gt;.52 seconds a page&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Whether you think that's fast or slow is going to be relative to how much energy you're willing to spend blindly clicking through a site trying to find those 12 buttons missing data attributes. &lt;/p&gt;

&lt;p&gt;Activating Puppeteer to either take screenshots or just expect it to be a SPA will slow things down significantly, so use that with caution. I mentioned that you can take screen shots with &lt;code&gt;-c&lt;/code&gt;, right?&lt;/p&gt;

&lt;p&gt;Did I also mention you can use &lt;code&gt;-f&lt;/code&gt; to pass in a whole CSS file? Because you can. And if you do, expect that to take a little longer, too. &lt;/p&gt;

&lt;h2&gt;
  
  
  Where can you see the code?
&lt;/h2&gt;

&lt;p&gt;You can view the &lt;a href="https://www.npmjs.com/package/selector-hound"&gt;package on NPM&lt;/a&gt; and you can &lt;a href="https://github.com/paceaux/selector-finder"&gt;look at the code on Github&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Feature requests and pull requests welcome.&lt;/p&gt;

</description>
      <category>css</category>
      <category>cli</category>
      <category>tools</category>
      <category>npm</category>
    </item>
    <item>
      <title>Using :not()? Try NOT to...</title>
      <dc:creator>Paceaux</dc:creator>
      <pubDate>Wed, 24 Jun 2020 02:38:12 +0000</pubDate>
      <link>https://dev.to/paceaux/using-not-try-not-to-18b0</link>
      <guid>https://dev.to/paceaux/using-not-try-not-to-18b0</guid>
      <description>&lt;p&gt;CSS is full of little gotchas and head scratchers. It’s also got a land mine or two that’s all too easy to step on. One of those landmines is the&lt;code&gt; :not() &lt;/code&gt;pseudo-class. &lt;/p&gt;

&lt;p&gt;As useful as it may &lt;em&gt;seem&lt;/em&gt;, I’d like to encourage you to &lt;em&gt;not&lt;/em&gt; use it, unless you really, &lt;em&gt;really&lt;/em&gt; mean to because  of the side-effects it brings.&lt;/p&gt;

&lt;h2&gt;What does &lt;code&gt;:not()&lt;/code&gt; do?&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;:not()&lt;/code&gt; is a pseudo-class. Like all pseudo-classes, &lt;em&gt;it targets a state&lt;/em&gt;. The most common pseudo-classes we see in our stylesheets are &lt;code&gt;:hover&lt;/code&gt; and &lt;code&gt;:focus&lt;/code&gt;, but we do have other fun friends like &lt;code&gt;:checked&lt;/code&gt;, &lt;code&gt;:target&lt;/code&gt;, and everyone’s loneliest, &lt;code&gt;:only-child&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;In the case of &lt;code&gt;:not()&lt;/code&gt;, the state that is being target is, well… a negative.&lt;em&gt; It targets a state of not being something&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;The goal of &lt;code&gt;:not()&lt;/code&gt; is to exclude certain elements from a particular ruleset&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
&lt;code&gt;:not()&lt;/code&gt; tells the browser “is not this”&lt;/h3&gt;

&lt;p&gt;CSS selectors are parsed right-to-left— but when a pseudo class is “chained” to something, the best way to read it is by saying, “that is also”. &lt;/p&gt;

&lt;p&gt;So we read the below selector as “every element with the class name &lt;code&gt;article&lt;/code&gt;, &lt;strong&gt;that is also not an element with the class name &lt;/strong&gt;&lt;code&gt; article--news&lt;/code&gt;“&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.article&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;.article--news&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&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;h3&gt;:not() also raises specificity &lt;em&gt;unexpectedly&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Pseudo-classes have the specificity of a &lt;em&gt;class&lt;/em&gt;.  Usually. &lt;/p&gt;

&lt;h4&gt;How a typical pseudo-class behaves&lt;/h4&gt;

&lt;p&gt;Styling a plain element (also known as a type selector) gets us a specificity of 0,0,1:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6ea5dc&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;Then we style the &lt;code&gt;:hover&lt;/code&gt; pseudo-class of this link element, getting the specificity 0,1,1:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6ea5c1&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;And if we wanted something special for targeting two states of this element, we’d get a specificity of 0,2,1: &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:hover:visited&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#7fb6d2&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;h4&gt;How  &lt;code&gt;:not()&lt;/code&gt; behaves may surprise you&lt;/h4&gt;

&lt;p&gt;Let’s suppose you wanted to target links that are not in a state of being &lt;code&gt;visited&lt;/code&gt;. You might write this:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:visited&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#6ea5c1&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 specificity on this selector is 0,1,1. &lt;/p&gt;

&lt;p&gt;Well that’s just like it was with &lt;code&gt;a:hover&lt;/code&gt;. What’s the big deal?&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;strong&gt;:not()&lt;/strong&gt;&lt;/code&gt;&lt;strong&gt; didn’t raise the specificity. &lt;/strong&gt;&lt;code&gt;&lt;strong&gt;:visited&lt;/strong&gt;&lt;/code&gt;&lt;strong&gt; did.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;It’s the argument within &lt;code&gt;:not()&lt;/code&gt; that raises specificity&lt;/h2&gt;

&lt;p&gt;Let’s suppose you’ve got a special style for your calls-to-action. Maybe they’re autogenerated and you feel the need to make a single, one-off case of making it different. It might be tempting to write this:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt; &lt;span class="nt"&gt;a&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;#call-to-action--3428&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First, let’s read that out-loud (go ahead, I won’t judge you):&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Every &lt;code&gt;a&lt;/code&gt; element that is also not an element with the &lt;code&gt;id call-to-action--3428&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Every element. Got it?&lt;/p&gt;

&lt;p&gt;Would you believe that the specificity of this style, on &lt;em&gt;every &lt;code&gt;a&lt;/code&gt; element&lt;/em&gt; is now 1,0,1 ? &lt;/p&gt;

&lt;p&gt;&lt;code&gt;:not()&lt;/code&gt; passes the specificity of the thing you’re excluding onto the thing your targeting. &lt;/p&gt;

&lt;p&gt;I’ll say that one more time for emotional effect:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;&lt;code&gt;:not() &lt;/code&gt;passes the specificity &lt;strong&gt;of the element you’re excluding&lt;/strong&gt; to &lt;strong&gt;the element you’re targeting.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Ugh.&lt;/p&gt;

&lt;h2&gt;Can’t we just set a best-practice; “don’t make the argument for &lt;code&gt;:not()&lt;/code&gt; higher than the target?”&lt;/h2&gt;

&lt;p&gt;So we’re saying &lt;code&gt;a:not(.nav__link)&lt;/code&gt; is off the table because this will target every link on the page and give it a specificity of 0,1,1; that’s an “unexpected” specificity.  &lt;/p&gt;

&lt;h3&gt;What if the &lt;em&gt;excluded &lt;/em&gt;specificity matches the &lt;em&gt;targeted&lt;/em&gt;? &lt;/h3&gt;

&lt;p&gt;Isn’t this safe with a specificity of 0,2,0?&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav__link&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#444&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s read this together:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;Every element with the class name &lt;code&gt;nav__link&lt;/code&gt; that also is not the &lt;code&gt;:last-child&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;Every. Element. &lt;/p&gt;

&lt;p&gt;Except one—and every element &lt;em&gt;except that one&lt;/em&gt; got the specificity of 0,2,0. &lt;/p&gt;

&lt;p&gt;You know how quickly this becomes a problem? Try the first time you add a hover state:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/*If this doesn't come later in the cascade, it's pointless*/&lt;/span&gt;
&lt;span class="nc"&gt;.nav__link&lt;/span&gt;&lt;span class="nd"&gt;:hover&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;#555&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;h3&gt;Ok, so can the excluded specificity be&lt;em&gt; less than&lt;/em&gt; the target’s specificity?&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ul .nav__link:not(:last-child)&lt;/code&gt; will get you a specificity of 0,2,1 on every &lt;code&gt;.nav__link&lt;/code&gt;, except one. You probably didn’t mean to do that. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;.nav__link:not(button)&lt;/code&gt;? Specificity of 0,1,1 on &lt;em&gt;every &lt;/em&gt; &lt;code&gt;nav__link&lt;/code&gt;. You probably didn't mean to do that, either. &lt;/p&gt;

&lt;p&gt;The thing is, it doesn’t matter what the argument is that you send into &lt;code&gt;:not()&lt;/code&gt;. Unless it’s &lt;code&gt;*&lt;/code&gt;, it’s going to raise the specificity on the targeted item. &lt;/p&gt;

&lt;p&gt;That’s right. This is the only thing that you can safely write:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav__link&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(*)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* Pull Request denied*/&lt;/span&gt;
  &lt;span class="nl"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;transparent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c"&gt;/* double-denied */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;Should you use &lt;code&gt;:not() &lt;/code&gt;to set “default styles”?&lt;/h2&gt;

&lt;p&gt;I’ve seen this pattern a few times in my life. Folks write out a “default style” using &lt;code&gt;:not()&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav__item&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,2,0*/&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the cost here is that theming is now more difficult. What should be a natural increase in specificity &lt;em&gt;isn’t&lt;/em&gt;. The below styles &lt;em&gt;only work &lt;/em&gt;if they come later in my stylesheet. &lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav--darkMode&lt;/span&gt; &lt;span class="nc"&gt;.nav__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,2,0 */&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So more than likely, I end up arbitrarily raising specificity (otherwise known as specificity bloat):&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav--darkMode&lt;/span&gt; &lt;span class="nc"&gt;.nav__item.nav__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,3,0 ...who hurt you?*/&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But, if I opt for a less terse selector that has clearer intent:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,1,0 */&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#333&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.nav__item&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,2,0 */&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We discover that theming can come without introducing dependencies on code organization:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav--darkmode&lt;/span&gt; &lt;span class="nc"&gt;.nav__item&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,2,0 */&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c"&gt;/* Pull Request Approved. Let's get beer. */&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;So when is &lt;code&gt;:not()&lt;/code&gt; safe?&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Rarely&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is really an article about &lt;em&gt;selector intent.&lt;/em&gt; Most of the time we write code thinking about what we &lt;em&gt;intend&lt;/em&gt; to style. Not what we &lt;em&gt;don’t&lt;/em&gt; intend to style. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;:not()&lt;/code&gt; is safest when you’ve reached an edge case. An edge-case is a point in your code where the scope is very small and you have a clear understanding that it won’t be expanded further.  &lt;/p&gt;

&lt;p&gt;A perfect example is picking up where we left off with a themed navigation item. In our last example, we got ourselves in a hole: we would have to remove border on the&lt;code&gt; last-child&lt;/code&gt; again:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav--darkmode&lt;/span&gt; &lt;span class="nc"&gt;.nav__item&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c"&gt;/* 0,3,0 */&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;none&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;em&gt;isn’t&lt;/em&gt; what we want. We don’t want to write code that makes us write more code. &lt;/p&gt;

&lt;p&gt;Now, suddenly, &lt;code&gt;:not()&lt;/code&gt; seems very useful:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.nav--darkmode&lt;/span&gt; &lt;span class="nc"&gt;.nav__item&lt;/span&gt;&lt;span class="nd"&gt;:not&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;:last-child&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;border-bottom&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1px&lt;/span&gt; &lt;span class="nb"&gt;solid&lt;/span&gt; &lt;span class="m"&gt;#fff&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We still raised the specificity (0, 3, 0) on our &lt;code&gt;.nav__item&lt;/code&gt;. But we did it on an edge-case at the benefit of not having to rewrite a pre-existing style. We wrote our selector with a clear intent of, “I don’t want to overwrite &lt;code&gt;:last-child&lt;/code&gt; &lt;strong&gt;except when&lt;/strong&gt; I’m dealing with a &lt;code&gt;.nav__item&lt;/code&gt; that’s within a &lt;code&gt;.nav--darkmode&lt;/code&gt; container.”&lt;/p&gt;

&lt;h2&gt;Avoid &lt;code&gt;:not()&lt;/code&gt;, but don’t ignore it&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Avoid it for excluding type selectors (elements)&lt;/li&gt;
&lt;li&gt;Avoid it for setting default styles&lt;/li&gt;
&lt;li&gt;Never pass in an element with a higher specificity than your target&lt;/li&gt;
&lt;li&gt;Prefer it in narrow scopes to address edge-cases&lt;/li&gt;
&lt;li&gt;Prefer it when it saves you from duplicating code at a higher specificity&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>css</category>
    </item>
    <item>
      <title>What’s the highest z-index on a page (and other CSS property problems)</title>
      <dc:creator>Paceaux</dc:creator>
      <pubDate>Fri, 24 Jan 2020 20:14:46 +0000</pubDate>
      <link>https://dev.to/paceaux/what-s-the-highest-z-index-on-a-page-and-other-css-property-problems-3a2j</link>
      <guid>https://dev.to/paceaux/what-s-the-highest-z-index-on-a-page-and-other-css-property-problems-3a2j</guid>
      <description>&lt;p&gt;Ever been the new person on an old project where you were trying to not make things substantially worse? Maybe you need to position an element, but you don’t know what &lt;code&gt;z-index&lt;/code&gt; value is safe to use. You don’t want to layer something to &lt;code&gt;z-index: 9999&lt;/code&gt; if &lt;code&gt;z-index: 10&lt;/code&gt; will suffice… but how do you find out what the highest &lt;code&gt;z-index&lt;/code&gt; is?&lt;/p&gt;

&lt;p&gt;Or, for that matter, how do you find everything that’s using &lt;code&gt;opacity&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Sure, you’ve got a modern browser with great debugging tools. But they don’t make it easy for you to search by CSS properties. So I wrote a JavaScript function that can do that.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remember the CSSOM?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://blog.frankmtaylor.com/?s=cssom"&gt;I’ve written about the CSSOM in the past&lt;/a&gt; (CSS Object Model) and I’ll say again that it’s an under-appreciated and under-utilized feature of the web browser environment.&lt;/p&gt;

&lt;p&gt;If you need to do something so peculiar as searching for selectors by CSS properties, this is the thing the CSSOM is good for.&lt;/p&gt;

&lt;h2&gt;
  
  
  It starts with the &lt;code&gt;stylesheets&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s start by creating a new function that’ll take two arguments; &lt;code&gt;queryPropName&lt;/code&gt; and &lt;code&gt;queryPropValue&lt;/code&gt;. We’ll access some &lt;code&gt;styleSheets&lt;/code&gt; and loop through them since they’re enumerable, but not an array.&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="nf"&gt;queryCSSByProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryPropValue&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;styleSheets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&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;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; 

  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Next, try to loop through the rules
&lt;/h3&gt;

&lt;p&gt;We’ll need to wrap the interior of our loop in a try-catch because the browser may throw some restrictions at us trying to access some of the &lt;code&gt;cssRules&lt;/code&gt;. Then we’ll loop through the rules of that &lt;code&gt;styleSheet&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;try&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;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 

        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&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;h3&gt;
  
  
  Then, look for a style on the rule
&lt;/h3&gt;

&lt;p&gt;Now that we’re inside of a rule inside of a &lt;code&gt;stylesheet&lt;/code&gt;, we’re where we need to be. So now what we want to do is see if the CSS property we want is there.&lt;/p&gt;

&lt;p&gt;First, let’s pull out some things that will be useful, like &lt;code&gt;style&lt;/code&gt;, which will be an object that contains every possible CSS property. Let’s also grab some &lt;code&gt;selectorText&lt;/code&gt;, which is strictly the CSS selector part of this ruleset (e.g. &lt;code&gt;.someSelector &amp;gt; h1 &amp;gt; .foo&lt;/code&gt; )&lt;/p&gt;

&lt;p&gt;Once we get that out, let’s be safe and check to be sure style is truthy. Not every &lt;code&gt;cssRule&lt;/code&gt; will have a style property.&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;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rule&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;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

          &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  And if there’s a style, check if it’s the one you want
&lt;/h4&gt;

&lt;p&gt;This is where some logic could probably be cleaned up.&lt;/p&gt;

&lt;p&gt;First, let’s use the &lt;code&gt;CSSOM&lt;/code&gt;, rather than &lt;code&gt;hasOwnProperty&lt;/code&gt; or for–in to find out if there’s a value for our property. &lt;code&gt;getPropertyValue&lt;/code&gt; turns out to be the perfect way to get the value off of a specific CSS property in our style.&lt;/p&gt;

&lt;p&gt;Next, because we want an option to see search by value of a property, we have &lt;code&gt;hasPropValMatch&lt;/code&gt; to tell us exactly that. And for right now, rather than &lt;code&gt;===&lt;/code&gt;, let’s use &lt;code&gt;indexOf&lt;/code&gt; because there’s always the chance that there’s an &lt;code&gt;!important&lt;/code&gt; floating here. It’d be better to search within the string rather than assume it’s a pure equality. We’ll probably need more robust matching in the future.&lt;/p&gt;

&lt;p&gt;Finally, we check if our &lt;code&gt;queryPropValue&lt;/code&gt; is there (because, after all, maybe you’re just interested in &lt;code&gt;z-index&lt;/code&gt;, not &lt;code&gt;z-index: 10&lt;/code&gt; ). If it is, let’s set a value to our map.&lt;/p&gt;

&lt;p&gt;We’ll make the key of our item the CSS selector, which is the &lt;code&gt;selectorText&lt;/code&gt;. Then we’ll make the value a mashup of the property name and the property value. It won’t be a duplicate of what’s written in the actual stylesheet — just what’s important for search purposes.&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="nx"&gt;style&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;propertyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&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;hasPropValMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;hasPropValMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finally, stitch it all together
&lt;/h3&gt;

&lt;p&gt;Once we’ve done all this, let’s make sure that we return those properties we’re setting values in:&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="nf"&gt;queryCSSByProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;queryPropValue&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;styleSheets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&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;properties&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheets&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;styleSheet&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;try&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;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cssRules&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rules&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rule&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rule&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;style&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;propertyValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&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;hasPropValMatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;indexOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;hasPropValMatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;queryPropValue&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;selectorText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;queryPropName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;propertyValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;properties&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;h2&gt;
  
  
  Final Result?
&lt;/h2&gt;

&lt;p&gt;You should be able to run &lt;code&gt;queryCSSByProperty('z-index')&lt;/code&gt; on this page and discover that there's over 60 CSS rulesets using z-index. Quite nicely though for dev.to, they're managing most of them with CSS custom properties. &lt;/p&gt;

&lt;p&gt;A function like this will help you not be that person who’s picking random numbers out of a hat. In fact, a function like this might be a useful way to make sure your element is always &lt;code&gt;lastzIndex + 1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Of course, this could have other uses, too, beyond &lt;code&gt;z-index&lt;/code&gt;. But you get the idea.&lt;/p&gt;

&lt;p&gt;BTW, the final version of this is a &lt;a href="https://gist.github.com/paceaux/2b163c39062ec7ed4d78f70d78e5a2fc"&gt;gist&lt;/a&gt;, if that’s what you’re looking for. &lt;/p&gt;

</description>
      <category>cssom</category>
      <category>css</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The Symbology of JavaScript Symbols</title>
      <dc:creator>Paceaux</dc:creator>
      <pubDate>Mon, 30 Dec 2019 19:52:03 +0000</pubDate>
      <link>https://dev.to/paceaux/the-symbology-of-javascript-symbols-3odm</link>
      <guid>https://dev.to/paceaux/the-symbology-of-javascript-symbols-3odm</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0la4np2r6w9bnejlqgav.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F0la4np2r6w9bnejlqgav.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There have been two things that have appeared in newer versions of JavaScript that I haven't understood: Symbols and Iterators. &lt;/p&gt;

&lt;p&gt;When it comes to code I have to learn by doing, no amount of reading Mozilla Developer Network was going to help me understand Symbols. &lt;/p&gt;

&lt;p&gt;So I finally decided to stop reading articles, crack open a JavaScript console, snap in to a Slim Jim, and figure out what Symbols are all about. &lt;/p&gt;

&lt;p&gt;And now that I think I understand some basics, I want to share them with you. &lt;/p&gt;

&lt;h2&gt;
  
  
  JavaScript Symbols are a new primitive
&lt;/h2&gt;

&lt;p&gt;If you read the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol" rel="noopener noreferrer"&gt;entry on the Mozilla Developer Network&lt;/a&gt; it'll tell you right there at the beginning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Symbol is a primitive data type&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's a big deal. The Symbol is right up there with &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, &lt;code&gt;Number&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, and nobody's favorite, &lt;code&gt;null&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Primitives are a bit like the protons and electrons; you mix and match them to make atoms (objects). Put enough of them together and you can make a &lt;del&gt;dying&lt;/del&gt; Death Star (it's called NPM).&lt;/p&gt;

&lt;p&gt;So the fact that I've been ignoring &lt;code&gt;Symbol&lt;/code&gt; is bad; I've been ignoring a fundamental piece of how we build in the JavaScript universe. &lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols are unequivocally unique
&lt;/h2&gt;

&lt;p&gt;This is something that's easy to read on (digital) paper, but maybe hard to accept in practice: When you create a &lt;code&gt;Symbol&lt;/code&gt; it is unique. Forever and for-always.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let ianMalcom = Symbol('Ian Malcom');
let ianMalcomClone = Symbol('Ian Malcom');

const ianMalcomWasWrong = (ianMalcom == ianMalcomClone); // false
const michaelCrichtonWasWrong = (ianMalcom === ianMalcomClone); // false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not only is every symbol ever created unique, you can't even compare two symbols with the same "value". &lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols don't coerce
&lt;/h2&gt;

&lt;p&gt;Remember everyone's favorite gag, that old &lt;code&gt;1 + '1' == '11'&lt;/code&gt;? Or &lt;code&gt;[1] + 1 == 11&lt;/code&gt;? I know you remember the one about the boolean throwing the baseball at the window: &lt;code&gt;true * ([1] + [1]) == 11&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Those are all fun type coercion games that we hope never come up in job interviews. &lt;/p&gt;

&lt;p&gt;Well guess what? &lt;/p&gt;

&lt;p&gt;Symbol don't play like that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const zildjian = Symbol('1');
zildjian + 1; // TypeError: can't convert symbol to number
zildjian + '1'; // TypeError: can't convert symbol to string
!!zildjian; // true. Huh.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So Symbols don't give into our concatenation shenanigans.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;So what are Symbols actually good for?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What good is an absolutely unique primitive that doesn't give into JavaScript's Weird Coercion Tricks®?&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols are Secret(ish)
&lt;/h2&gt;

&lt;p&gt;Let's suppose some sort of library that we're bringing into our codebase. We're making some dinosaurs, but maybe we don't have that bit about getting dinos to reproduce. &lt;/p&gt;

&lt;p&gt;The old school way might be something like this:&lt;br&gt;
&lt;/p&gt;

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

const tRex = Object.assign(
  {
    reproduce() {
     return null;
    }
  },
  dinosaurs); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This seems fine, except ... it's easy to create a scenario where everyone dies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Step 1. Let's create a bigger t-rex
const megaTRex = Object.assign({}, tRex);

// Step 2. t-rexes get lonely because they have no one to hug
megaTRex.reproduce = function () {
  return this;
};

// Step 3. You know what no one asked for? Velociraptor + t-rex
const velociTrex = Object.assign(velociraptor, megaTrex);


// Step 4. Hey, turns out we've got this .reproduce function, WCGW?
velociTrex.reproduce(); // returns zero rescues from Chris Pratt

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

&lt;/div&gt;



&lt;p&gt;Sometimes, when we add a feature on to an object, we want it &lt;em&gt;just&lt;/em&gt; for that object. We don't want others to see what we've been doing and to use it themselves.  &lt;/p&gt;

&lt;h2&gt;
  
  
  Symbol is a secret password
&lt;/h2&gt;

&lt;p&gt;What if we created our own private way to help that &lt;code&gt;megaTRex&lt;/code&gt; reproduce? One that no one else could know about? &lt;/p&gt;

&lt;p&gt;Let's go back to our &lt;code&gt;megaTRex&lt;/code&gt; and try again. But this time, we'll use a &lt;code&gt;Symbol&lt;/code&gt; as the &lt;em&gt;key&lt;/em&gt; for our object (this is called a symbol-keyed property):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const megaReproducer= Symbol('reproduce');

const megaTRex= Object.assign({}, tRex);

megaTRex[megaReproducer] = function () { 
  return this;
}

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

&lt;/div&gt;



&lt;p&gt;Guess what? You're not going to find that on the object! If you trying to find this &lt;code&gt;megaReproducer&lt;/code&gt; with &lt;code&gt;for-in&lt;/code&gt;, you're not going to find it. &lt;/p&gt;

&lt;p&gt;In the Firefox console, you'll see something like this if you inspect the object:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdvq3wny0cai1wlh7bzla.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fdvq3wny0cai1wlh7bzla.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that it's there, but you're not going to find it in any of your typical approaches you might think of for finding properties on an object or its prototype. &lt;/p&gt;

&lt;p&gt;None of these will reveal a property-keyed Symbol:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (property in megaTRex) {
 console.log(megaTrex[property])
}

Object.keys(megaTRex).forEach(property =&amp;gt; console.log(propertyName));

for (let [propertyName, value] of Object.entries(megaTRex)) {
  console.log(propertyName, value);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll have to use &lt;code&gt;Object.getOwnPropertySymbols&lt;/code&gt; if you want to find the symbols living on an object. So it's not like Symbol-keyed property is invisible; it's just chilling on an island you weren't thinking of looking on. &lt;/p&gt;

&lt;p&gt;But, looking is one thing. How do you access it?&lt;/p&gt;

&lt;h3&gt;
  
  
  It takes a symbol to know a symbol
&lt;/h3&gt;

&lt;p&gt;You might be able to inspect an object and see that a symbol is a key on it. But you don't have any way to access it — &lt;em&gt;unless you have the symbol you used to create it&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;What this means is that we get a good fair amount of privacy and protection for our objects. The &lt;code&gt;Symbol&lt;/code&gt; is a way to extend an object, maybe even an object you don't really "own" -- and do it in a safe way where you don't open up risks of abuse elsewhere in your runtime. &lt;/p&gt;

&lt;p&gt;The only way this &lt;code&gt;megaTRex&lt;/code&gt; is going to make a baby T-rex is if you have that exact &lt;code&gt;Symbol&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const newMegaTRex = megaTrex[megaReproducer]()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is especially practical in cases where we are importing from a library and exporting code to be used elsewhere:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import {tRex} from 'dinosaurs.js';
const keyToReproduction = Symbol('frogs');

tRex[keyToReproduction] = function () {

    return this;

}

export const megaTRex = tRex[keyToReproduction]();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've safely extended our library and exported a product &lt;em&gt;after&lt;/em&gt; that extension — without exporting the ability to access that function. &lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols don't collide
&lt;/h2&gt;

&lt;p&gt;Going back to the fact that a &lt;code&gt;Symbol&lt;/code&gt; is absolutely unique. This turns out to be handy for another reason: it prevents accidental overwrites. &lt;/p&gt;

&lt;p&gt;Let's step away from uncited Michael Crichton fan-fiction for a minute and talk through a slightly more practical example: extending the &lt;code&gt;console&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Let's suppose we're dealing with a particularly fickle library, and we need to do a lot of logging. &lt;/p&gt;

&lt;p&gt;Maybe we want to have a nice formatted &lt;code&gt;console.log&lt;/code&gt;, because we're developers and of course we'd want this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let pretty= Symbol('logPretty');

console.log[pretty] = function (message, styles= 'font-size: 1.5em; color: #bad') {
  console.log(`%c ${message}`, styles);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cool. Because we've used a &lt;code&gt;Symbol&lt;/code&gt; for extending the console, we're safe from any browser ever adding &lt;code&gt;console.log.pretty&lt;/code&gt; in the near or distant future. &lt;/p&gt;

&lt;h3&gt;
  
  
  This is a great way to extend globals in the browser!
&lt;/h3&gt;

&lt;p&gt;As long as we've got access to that &lt;code&gt;pretty&lt;/code&gt; variable, we can write &lt;code&gt;console.log[pretty]('Hey there')&lt;/code&gt; and see all the delightful console messages we want. &lt;/p&gt;

&lt;p&gt;Just, uh, remember that you need that &lt;em&gt;exact&lt;/em&gt; symbol. Which means...&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid Collisions with &lt;code&gt;const&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;You may have noticed that I used &lt;code&gt;let&lt;/code&gt; in my example above. &lt;br&gt;
This is bad. Don't do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// uh oh. I reassigned my variable
pretty = Symbol('newPretty');
console.log[pretty] = function (message, styles = 'font-size: 3em; color: red') {
  console.log(`%c ${message}`, styles)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I have no easy way to get back my old "pretty" symbol. &lt;/p&gt;

&lt;p&gt;I should've used &lt;code&gt;const&lt;/code&gt; so my variable couldn't be reassigned. That was dumb. &lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieving lost Symbols
&lt;/h3&gt;

&lt;p&gt;How can I ever outshine other developers on my team without this precious symbol? Will I ever be able to get my long lost symbol back, so that I can make my logs pretty again?&lt;/p&gt;

&lt;p&gt;Of course. I need to use &lt;code&gt;getOwnPropertySymbols&lt;/code&gt; and quit being melodramatic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [oldPretty, newPretty] = Object.getOwnPropertySymbols(console.log);

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

&lt;/div&gt;



&lt;p&gt;Which reminds me...&lt;/p&gt;

&lt;h3&gt;
  
  
  Describe your Symbols
&lt;/h3&gt;

&lt;p&gt;Wen you create a Symbol, it doesn't &lt;em&gt;need&lt;/em&gt; a 'descriptor'. You can make plain ol' ordinary undescriptive &lt;code&gt;Symbol&lt;/code&gt;s:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const prettyBad = Symbol();

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

&lt;/div&gt;



&lt;p&gt;Much like cloning dinosaurs, this is probably a bad idea. &lt;/p&gt;

&lt;p&gt;If you're using Symbol-keyed properties, and you need  to use &lt;code&gt;getOwnPropertySymbols&lt;/code&gt;, that descriptor is going to be the key to figuring out which is the prettiest log of them all:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsk2zhhpeemtxrnaeul9n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fsk2zhhpeemtxrnaeul9n.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I should add, by the way, that while you &lt;em&gt;could&lt;/em&gt; use the same descriptor for every symbol-keyed property, that doesn't mean you &lt;em&gt;should&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmwluj12jjvcc3ole0rx7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fmwluj12jjvcc3ole0rx7.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Symbols don't &lt;code&gt;stringify()&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;JSON.stringify&lt;/code&gt; ignores Symbols completely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { dna } from 'dinosaurs';

const reproduction = Symbol('frogs');
const howToCloneDinosaurs = {
  richDudes: 1,
  newman: 0,
  cynicalMathematicians: 1,
  paleontologists: 2,
  island: 'isla nublar',
  lawyers: Infinity
};

howToCloneDinosaurs[reproduction] = dna;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftee11d4lba3mwi8j2as5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftee11d4lba3mwi8j2as5.jpg" alt="console output of json.stringify where lawyers are deservedly null and a symbol-keyed property isn't there"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think this is a Good Thing™. &lt;/p&gt;

&lt;h3&gt;
  
  
  It prevents cloning
&lt;/h3&gt;

&lt;p&gt;The most common way to deep-clone objects in JavaScript is with &lt;code&gt;JSON.parse(JSON.stringify())&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;A Symbol-keyed property is a simple and terse way to put a property on an object that you don't want to be cloned. &lt;/p&gt;

&lt;p&gt;Of course, you can &lt;em&gt;also&lt;/em&gt; use the always-clunky, super verbose, always-have-to-look-it-up &lt;code&gt;Object.defineProperty()&lt;/code&gt; to make a property unJSON.stringifiable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object.defineProperty(howToCloneDinosaurs,'reproduction', {
 value: dna,
 enumerable: false
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Object.defineProperty&lt;/code&gt; might make sense when we need to define a &lt;code&gt;lot&lt;/code&gt; of things about a property. But if we want an easy way to make sure the property and its value aren't cloned, Symbol seems the way to go. &lt;/p&gt;

&lt;h2&gt;
  
  
  There's some built-in Symbols
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol#Well-known_symbols" rel="noopener noreferrer"&gt;Turns out, there's a slew of "built-in" symbols that exist&lt;/a&gt;. I won't list them all here, but there's a few that catch my eye as particularly interesting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Symbol.iterator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Symbol.asyncIterator&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Symbol.split&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Symbol.toStringTag&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reason these are of interest to me (and should be of interest to you) is because these are "Symbol Keys" that allow us to define our own behaviors on objects. These behaviors didn't used to be available to us, but now they are!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a String that iterates by word
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;for of&lt;/code&gt; is kinda awesome, but it only works on things that are &lt;em&gt;iterable&lt;/em&gt; (more on what that means in another post. &lt;/p&gt;

&lt;p&gt;Let's use &lt;code&gt;Symbol.iterator&lt;/code&gt; and make a string iterable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function WordString(text) {
    const string = new String(text); // make explicit object
    const words = string.split(' '); // split by spaces
    let wordIndex = 0;

    string[Symbol.iterator] = function* stringIterator() {
      while (wordIndex &amp;lt; words.length) {
       yield words[wordIndex++]
        .replace(new RegExp('[!.?]', 'g'),''); // remove any punctuation
      }
    }

    return string;
}

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

&lt;/div&gt;



&lt;p&gt;Ignore the &lt;code&gt;*&lt;/code&gt; and the &lt;code&gt;yield&lt;/code&gt; for right now. Those are things for iterators. Just dial in on the fact that we used a global Symbol key (&lt;code&gt;Symbol.iterator&lt;/code&gt;) and we used it to make something that &lt;em&gt;wasn't iterable&lt;/em&gt; ... &lt;em&gt;iterable&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Look at what we can do with this fancy &lt;code&gt;WordString&lt;/code&gt; now:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffyvaejs5domvfzh2mup2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffyvaejs5domvfzh2mup2.jpg" alt="Output in a console using for-of where each word in the string "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Create an Honest Array
&lt;/h3&gt;

&lt;p&gt;If you read my &lt;a href="https://dev.to/paceaux/kyle-simpson-proved-i-still-don-t-know-javascript-2fnp"&gt;previous post on arrays&lt;/a&gt; you might recall that there's an implicit and explicit &lt;code&gt;undefined&lt;/code&gt;. Maybe you're disappointed that arrays are liars sometimes. &lt;/p&gt;

&lt;p&gt;Let's use &lt;code&gt;Symbol.species&lt;/code&gt; to tell us that this is still an array. And then we'll throw a generator function on that array and define what &lt;code&gt;for of&lt;/code&gt; will actually return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class TruthyArray extends Array {
    constructor(value) {
        super(...value);  
        this.value = [...value];
    }
    get [Symbol.species]() {
      return Array;
    }
    *[Symbol.iterator]() {
      let itemIndex = -1;
          while (itemIndex &amp;lt; this.value.length ) {
              if (this.value[++itemIndex]) {
                  yield this.value[itemIndex];
              }
          }
      }
  }

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

&lt;/div&gt;



&lt;p&gt;Again, ignore the &lt;code&gt;*&lt;/code&gt; and the &lt;code&gt;yield&lt;/code&gt;. That's for another time. &lt;/p&gt;

&lt;p&gt;The greater point is that &lt;code&gt;Symbol&lt;/code&gt; has some built-in "keys" that we can add to an object to extend functionality. &lt;/p&gt;

&lt;h2&gt;
  
  
  The Recap
&lt;/h2&gt;

&lt;p&gt;Dev.to says this is a 9-minute read. That's like 2 cigarette breaks or one visit to the bathroom after a tryst with a holiday cheese plate. &lt;/p&gt;

&lt;p&gt;I don't want to keep you much longer or someone will be looking for you... and, "I was reading an article about Frank's Jurassic Park-inspired JavaScript Symbol fan fiction,"  is not how you want to explain yourself. You're a professional. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Symbol&lt;/code&gt; is a primitive. It's worth knowing because it's in the guts of how everything works in JS now. &lt;/li&gt;
&lt;li&gt;Symbols are unique and it's best not to think about &lt;em&gt;how&lt;/em&gt; they're unique. But they are.&lt;/li&gt;
&lt;li&gt;Symbols don't coerce into other things. They laugh in the face of your &lt;code&gt;+&lt;/code&gt; jokes. &lt;/li&gt;
&lt;li&gt;You can and probably &lt;em&gt;should&lt;/em&gt; be making property-keyed symbols. &lt;/li&gt;
&lt;li&gt;Symbol-keyed properties guarantee you'll never have collision; that makes it the perfect way to extend browser built-ins or libraries. &lt;/li&gt;
&lt;li&gt;Symbol-keyed properties are hidden-ish. &lt;code&gt;JSON.stringify&lt;/code&gt; ignores them, &lt;code&gt;for-in&lt;/code&gt;, &lt;code&gt;Object.keys&lt;/code&gt; ignores them, too. You have to know you're looking for a property-keyed  Symbol. &lt;/li&gt;
&lt;li&gt;You need your Symbol to access a symbol-keyed property, so use &lt;code&gt;const&lt;/code&gt; for defining it, or otherwise make sure you throw descriptors on that sucker lest it become lost forever and foralways. &lt;/li&gt;
&lt;li&gt;It's not just about &lt;code&gt;Symbol&lt;/code&gt;. The Symbol is how we access utilities previously unavailable to us on objects. &lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Shoutouts
&lt;/h3&gt;

&lt;p&gt;Thanks to &lt;a href="https://isabela.dev/" rel="noopener noreferrer"&gt;Isabela Moreira&lt;/a&gt; and &lt;a href="https://github.com/alex-klock" rel="noopener noreferrer"&gt;Alex Klock&lt;/a&gt; for providing technical review of this. &lt;/p&gt;

</description>
      <category>javascript</category>
      <category>symbols</category>
    </item>
    <item>
      <title>Kyle Simpson proved I STILL don't know JavaScript (arrays)</title>
      <dc:creator>Paceaux</dc:creator>
      <pubDate>Fri, 06 Dec 2019 17:26:49 +0000</pubDate>
      <link>https://dev.to/paceaux/kyle-simpson-proved-i-still-don-t-know-javascript-2fnp</link>
      <guid>https://dev.to/paceaux/kyle-simpson-proved-i-still-don-t-know-javascript-2fnp</guid>
      <description>&lt;p&gt;If you've never read Kyle Simpson's fantastic series, &lt;a href="https://www.amazon.com/gp/product/B07FK9VBD7/?ie=UTF8&amp;amp;%2AVersion%2A=1&amp;amp;%2Aentries%2A=0" rel="noopener noreferrer"&gt;You Don't know JS&lt;/a&gt;, I'd first encourage to stop reading this, go read &lt;em&gt;that&lt;/em&gt; , and then come back.  It might take about six weeks, but that's fine. I'll wait. &lt;/p&gt;

&lt;p&gt;...&lt;br&gt;
...&lt;br&gt;
...&lt;/p&gt;

&lt;p&gt;I see you came back. Great. Feel like you know JavaScript now? You sure? Go back and read it again. I'll wait. This post isn't going anywhere. &lt;/p&gt;

&lt;p&gt;...&lt;br&gt;
...&lt;br&gt;
...&lt;/p&gt;

&lt;p&gt;Feel like you really know JS now? Fantastic.  Let's talk about that simplest of data structures, the array, and what I didn't know after reading that book series &lt;em&gt;four times&lt;/em&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  JavaScript, I thought I knew you...
&lt;/h2&gt;

&lt;p&gt;First I want to point you to &lt;a href="https://twitter.com/getify/status/1201203738129641473" rel="noopener noreferrer"&gt;this twitter thread&lt;/a&gt; where, in the &lt;a href="https://twitter.com/getify/status/1201272013429575681" rel="noopener noreferrer"&gt;third tweet in the series&lt;/a&gt;, Kyle makes this statement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;just for clarity sake, this is what I find surprising...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FEKvGh0vXsAEHdIq%3Fformat%3Dpng%26name%3Dsmall" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FEKvGh0vXsAEHdIq%3Fformat%3Dpng%26name%3Dsmall" alt="kyle simpson showing an array created with commas in foreach and for of where the foreach doesn't show undefined but the for of does"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, I looked at that image and thought, "this makes sense. But... why does it make sense?"&lt;/p&gt;

&lt;p&gt;The more I tried to think about why it made sense, the more I realized I didn't know JavaScript. &lt;/p&gt;
&lt;h2&gt;
  
  
  First, a primer on making arrays
&lt;/h2&gt;

&lt;p&gt;There's a few different ways to make arrays in JavaScript. They amount to, "you can instantiate them with data, or without data". &lt;/p&gt;
&lt;h3&gt;
  
  
  Instantiating with data
&lt;/h3&gt;

&lt;p&gt;Sometimes we need to write an array with data already in it. It's not uncommon to do this when you don't expect that list to really change after you declare it. So there's two ways we instantiate that array: &lt;/p&gt;
&lt;h4&gt;
  
  
  Using the &lt;code&gt;Array&lt;/code&gt; constructor
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mistakes = new Array('my liberal arts degree', 'eating 15 slim jims')`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is considered weird and generally a bad practice in JavaScript. I'll explain why in a bit. &lt;/p&gt;
&lt;h4&gt;
  
  
  Using the Array Literal
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const moreMistakes = [tequila', 'Michael Bay\'s TMNT movie'];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the more common approach that I hope most of us are using at home.  &lt;/p&gt;
&lt;h3&gt;
  
  
  Instantiating without data
&lt;/h3&gt;

&lt;p&gt;In cases where we're moving data from one data structure to another we often declare an empty array and &lt;em&gt;then&lt;/em&gt; modify it.&lt;/p&gt;

&lt;p&gt;An extremely common pattern is declaring the empty array and then pushing 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;const moreFutureMistakes = [];

moreFutureMistakes.push('TMNT sequels')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if you want to be &lt;em&gt;that person&lt;/em&gt;, of course you can use the array constructor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const moreUnusualMistakes = new Array();

moreUnusualMistakes.push('what you\'re going to see next');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Weird ways to instantiate arrays
&lt;/h3&gt;

&lt;p&gt;I don't think I've ever really seen these in the wild, but they've always been there in the back of my mind. Kind of like the Hawaii 5-0 theme song. It's not really doing anything in my brain other than sitting there. Making sure I don't forget it. &lt;/p&gt;

&lt;p&gt;One of the only things I remember from my C++ class was that arrays had to have sizes. And I didn't know why. I still don't know why. (answer:&lt;code&gt;somethingSomething[memory]&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;So three weird ways of instantiating arrays involve setting the size of it up front:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const superSizeMe = [];
superSizeMe.length = 3; // SURPRISE! Length is a setter

const preSized = new Array(3); // "This won't confuse anyone," said no one ever.

const commaSized= [,,,]; 

const isWeirdButTrue= (superSizeMe.length === preSized.length === commaSized.length);

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

&lt;/div&gt;



&lt;p&gt;If you were wondering why it's considered bad practice to use the &lt;code&gt;Array&lt;/code&gt; constructor, now you know. It's because if you give it exactly one argument, and that argument is an Integer, it will create an array of that size. So the array constructor could get unexpected results when dealing with numbers. &lt;/p&gt;

&lt;p&gt;And it's not like any of the other approaches are remotely close to best-practice, either. They're all the strange practices of someone who's maybe a little too curious for their own good or perhaps wondering if the trickster-god Loki is in fact alive and designing programming languages. &lt;/p&gt;

&lt;h2&gt;
  
  
  Weird Instantiations and Weird ways to set data result in &lt;del&gt;weird results&lt;/del&gt; totally expected behavior.
&lt;/h2&gt;

&lt;p&gt;Now we're caught up and back to Kyle's tweet about how weird this is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[,,,3,4,,5].forEach(x=&amp;gt;console.log(x));
// 3
// 4
// 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Ok, let's agree that comma-instantiated arrays is weird.&lt;/li&gt;
&lt;li&gt;Ok. It logged... 3,4,5 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is fine. Everything's fine. those other slots must be &lt;code&gt;undefined&lt;/code&gt; or unavailable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for (let x of [,,,3,4,,5]) { console.log(x); }
// undefined 
// undefined
// undefined
// 3
// 4
// undefined
// 5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hold up....&lt;/p&gt;

&lt;h3&gt;
  
  
  What's in those "weirdly instantiated arrays" ?
&lt;/h3&gt;

&lt;p&gt;Let's take a step back and look at these pre-sized arrays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myRegrets = new Array(3);
const moreRegrets = [,,,];
const noRegerts = [];

noRegerts.length = 3;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using Firefox, crack open the console, run this, and take a look at those arrays. &lt;/p&gt;

&lt;p&gt;You might see something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array(3) [undefined, undefined, undefined]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  But is that array &lt;em&gt;really&lt;/em&gt; filled with three &lt;code&gt;undefined&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;No. Not it is not. That's what Kyle Simpson is aptly pointing out. If you loop through these "pre-sized" arrays, and try to log the value, you will not get a log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myRegrets = new Array(3);
myRegrets.forEach((regret, regretIndex) =&amp;gt; {
  console.log(regret, regretIndex);
});


for (regretName in myRegrets) {
 console.log(regretName, myRegrets[regretName]);
}

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

&lt;/div&gt;



&lt;p&gt;So, the first big takeaway here is that a pre-sized array, &lt;em&gt;or&lt;/em&gt; an array created with comma/slots, doesn't have a &lt;em&gt;value&lt;/em&gt; in those slots. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;myRegrets&lt;/code&gt; is not an array with 3 &lt;code&gt;undefined&lt;/code&gt;. It's an array with three slots of &lt;em&gt;nothing&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;To further prove this point, add an &lt;em&gt;actual&lt;/em&gt; &lt;code&gt;undefined&lt;/code&gt; to the third slot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myRegrets = new Array(3);
myRegrets[1] = undefined; 
myRegrets.forEach((regret, regretIndex) =&amp;gt; {
  console.log(regret, regretIndex);
});


for (regretName in myRegrets) {
 console.log(regretName, myRegrets[regretName]);
}

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

&lt;/div&gt;



&lt;p&gt;You got a log, didn't you? Just one, right? &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Double-you Tee Eff&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  There's an &lt;em&gt;implicit&lt;/em&gt; and &lt;em&gt;explicit&lt;/em&gt; &lt;code&gt;undefined&lt;/code&gt; in Arrays
&lt;/h2&gt;

&lt;p&gt;This is what I think Kyle is talking about here. &lt;/p&gt;

&lt;p&gt;When we do these weird Array tricks where we pre-size it, or we comma-slot it (e.g. &lt;code&gt;[,,undefined]&lt;/code&gt;), JavaScript isn't actually putting values in those slots. Instead, it's saying the slots &lt;em&gt;exist&lt;/em&gt; ... &lt;em&gt;kinda&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;If something exists, but has no value, we have a name for that:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myRegrets = [,,undefined];
const youWillRegretThis;

myRegrets[0] === youWillRegretThis; // true, so very true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I call this "implicit undefined" because this doesn't get logged in any looping that we do. Not &lt;code&gt;forEach&lt;/code&gt;, neither &lt;code&gt;for - in&lt;/code&gt;, nor &lt;code&gt;map&lt;/code&gt; and its buddies will log a slot that has no value; i.e. implicitly undefined;&lt;/p&gt;

&lt;p&gt;You could also call this "undeclared" if you don't like "implicitly undefined". &lt;/p&gt;

&lt;h3&gt;
  
  
  Explicit &lt;code&gt;undefined&lt;/code&gt; must take up memory
&lt;/h3&gt;

&lt;p&gt;When you loop over an array with an &lt;em&gt;explicit undefined&lt;/em&gt; , it must be taking up actual memory. And that's why it gets logged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const myRegrets = [,,undefined];

myRegrets.forEach((regret, regretIndex) =&amp;gt; {
  console.log(regret, regretIndex);
});
// will log 3

for (regretName in myRegrets) {
 console.log(regretName, myRegrets[regretName]);
}

// will log 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So just remember this, kids. There's an implicit undefined and an explicit undefined when it comes to arrays. &lt;/p&gt;

&lt;p&gt;This probably won't be a thing you trip on any time soon unless you merge arrays. &lt;/p&gt;

&lt;p&gt;Or use &lt;code&gt;for of&lt;/code&gt;...&lt;/p&gt;

&lt;p&gt;Wait. &lt;code&gt;for of&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;yes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Double-you tee ay eff)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;for - of&lt;/code&gt; is the only looping mechanism that doesn't care about implicit or explicit undefined.
&lt;/h2&gt;

&lt;p&gt;Again, think of "implicit undefined" as meaning, "undeclared":&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
const myRegrets = [,,undefined];


let regretCounter = 0;

for (regret of myRegrets) {
 console.log(regret, regretCounter++)
}
// undefined 0
// undefined 1
// undefined 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why did it log all three?&lt;/p&gt;

&lt;p&gt;I don't know for certain, but I have a &lt;em&gt;theory&lt;/em&gt; that a much smarter person than I needs to investigate. &lt;/p&gt;

&lt;p&gt;The &lt;code&gt;for of&lt;/code&gt; pattern implements an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols" rel="noopener noreferrer"&gt;iteration protocol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My theory here is that the iteration protocol on arrays behaves something like what's shown from the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#Iterator_examples" rel="noopener noreferrer"&gt;examples page&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;function makeIterator(array) {
    var nextIndex = 0;

    return {
       next: function() {
           return nextIndex &amp;lt; array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;if &lt;code&gt;for - of&lt;/code&gt; implements something like this under the hood, this will iterate by index, not property (and arrays are really just objects with properties that are numbers. kinda).&lt;/p&gt;

&lt;p&gt;So, back to what we call a thing that exists but has no value. You know the one. Our old friend. The one we never invite to parties but he shows up anyway? Remember him? &lt;/p&gt;

&lt;p&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;I'm really starting to not like that guy. He weirds me out.&lt;/p&gt;

&lt;p&gt;TL;DR&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;.length&lt;/code&gt; property of an array isn't the same as saying, "these many slots have value"&lt;/li&gt;
&lt;li&gt;Arrays can have "implicit undefined", and "explicit undefined", depending on whether the space really has a value and "implicit undefined" is more like, "undeclared"&lt;/li&gt;
&lt;li&gt;If you don't create arrays in weird ways, or do weird things with arrays, you'll likely never encounter this&lt;/li&gt;
&lt;li&gt;If you are that trickster god Loki, or a fan, and choose to create arrays in weird ways, or manipulate them weirdly, you may need to use &lt;code&gt;for of&lt;/code&gt; to get the most consistent result while looping. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;JavaScript makes a lot of sense early in the morning. Not late at night.&lt;/p&gt;

&lt;h1&gt;
  
  
  [Edit: Some additions]
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A few comments on this post made me do some research and testing that some may find useful&lt;/em&gt;. This was already a long read, so unless you're camped out in a bathroom stall on account of a late-night binge on cheese, or you're otherwise really interested in talking about specifications, you can skip this stuff. &lt;/p&gt;

&lt;h2&gt;
  
  
  Are there array properties that are simply being set as not enumerable?
&lt;/h2&gt;

&lt;p&gt;I don't &lt;em&gt;think&lt;/em&gt; so. &lt;/p&gt;

&lt;p&gt;I skimmed through some &lt;a href="https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf" rel="noopener noreferrer"&gt;ECMA specs&lt;/a&gt; to see if this behavior is defined anywhere. &lt;/p&gt;

&lt;h3&gt;
  
  
  The specs say that array elements without assignment expressions are not defined
&lt;/h3&gt;

&lt;p&gt;Section 12.2.5 says&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Whenever a comma in the element list is not preceded by an AssignmentExpression (i.e., a comma at the beginning or after another comma), the missing array element contributes to the length of the Array and increases the index of subsequent elements. &lt;em&gt;Elided array elements are not defined.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So if you have &lt;code&gt;[,,'foo']&lt;/code&gt;, those array elements after the comma that don't have some sort of expression are "elided". &lt;/p&gt;

&lt;p&gt;Also worth noting is that the specs say that &lt;code&gt;['foo',]&lt;/code&gt; does &lt;em&gt;not&lt;/em&gt; contribute to the length of the array.&lt;/p&gt;

&lt;p&gt;Also &lt;em&gt;also&lt;/em&gt; worth noting is that I haven't yet found if pushing values to a random index above the length counts as elision. e.g.:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const gapped = [];
gapped[2] = "please mind the gap";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The specs don't seem to state that array elements are created but not enumerable
&lt;/h3&gt;

&lt;p&gt;Step 8 of section 22.1.1.3 describes how an array is created:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Repeat, while k &amp;lt; numberOfArgs&lt;br&gt;
a. Let Pk be ! ToString(k)&lt;br&gt;
b. Let itemK be items[k]&lt;br&gt;
c. Let defineStatus be CreateDataProperty(array, Pk, itemK)&lt;br&gt;
d. Assert: defineStatus is true&lt;br&gt;
e. Increase k by 1&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;Pk&lt;/code&gt; is the key (which is an index) and &lt;code&gt;itemK&lt;/code&gt; is the value. &lt;/p&gt;

&lt;p&gt;If the JavaScript engine is following this algorithm, an item, regardless of its value, gets passed into the &lt;code&gt;CreateDataProperty&lt;/code&gt; function/method/whatever.&lt;/p&gt;

&lt;p&gt;The question is, "does the first slot in &lt;code&gt;[,,'foo']&lt;/code&gt; constitute being an &lt;em&gt;item&lt;/em&gt;? 12.2.5 says no. (I think)&lt;/p&gt;

&lt;h3&gt;
  
  
  But is there a chance &lt;code&gt;CreateDataProperty&lt;/code&gt; is creating a property making it non-enumerable?
&lt;/h3&gt;

&lt;p&gt;If you read in section 7.3.4, it doesn't give any logic or condition where the &lt;code&gt;enumerable&lt;/code&gt; property in the descriptor . Steps 3 and 4 set the property to be enumerable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt; Let newDesc be the PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]:true }.&lt;/li&gt;
&lt;li&gt; Return ? O.&lt;a href="https://dev.toP,%20newDesc"&gt;[DefineOwnProperty]&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;I haven't read through &lt;em&gt;all&lt;/em&gt; the specification has to say about arrays. But this seems further suggest that these "empty slots" are &lt;em&gt;really empty&lt;/em&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  What about the &lt;code&gt;in&lt;/code&gt; operator. Will it find these empty slots?
&lt;/h3&gt;

&lt;p&gt;No it will not!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const slotted = [,,'one'];
let i = 0;

while (i &amp;lt; slotted.length) {
 if (i++ in slotted) {
  console.log(`${i - 1} is in the array`);
 }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will log exactly once, displaying &lt;code&gt;2 is in the array&lt;/code&gt; in your console. &lt;/p&gt;

&lt;p&gt;If you have an &lt;em&gt;explicit&lt;/em&gt; &lt;code&gt;undefined&lt;/code&gt;, however&lt;code&gt;const explicit = [undefined, undefined, 'one']&lt;/code&gt; , it will log three times. &lt;/p&gt;

&lt;h2&gt;
  
  
  STL;SDR (Still too long, still didn't read)
&lt;/h2&gt;

&lt;p&gt;First, let me caveat everything by telling you I'm way more qualified to talk to you about French Existentialism than JavaScript. The likelihood that all this is wrong is pretty high. &lt;/p&gt;

&lt;p&gt;Based on my understanding of the specifications, "implicit undefined" is a somewhat valid-ish way to describe a "slot" in an array that has no value. &lt;/p&gt;

&lt;p&gt;Except, of course, there's not really even a slot. There's not even the idea of a slot. A slot does not exist without a value. (#Existentialism)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/types%20%26%20grammar/ch1.md#undefined-vs-undeclared" rel="noopener noreferrer"&gt;As Kyle Simpson points out&lt;/a&gt; there is a difference between &lt;code&gt;undefined&lt;/code&gt; and &lt;code&gt;undeclared&lt;/code&gt; but JavaScript doesn't always give you messaging that makes it clear which is which. &lt;/p&gt;

&lt;p&gt;This "implicit undefined" is more of an existential problem where we only have so many ways to describe Being and Nothingness.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const existentialCrisis= [,undefined,'Waiting for Godot']`;
console.log(typeof existentialCrisis[1]); // undefined
console.log(typeof existentialCrisis[0]); // undefined

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

&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>todayilearned</category>
    </item>
  </channel>
</rss>
