`).
+- You can nest `var()` calls, using another variable as fallback (e.g. `var(--main-color, var(--other-color))`), pass them to other functions such as `calc()` or even assign one variable to another (e.g. `--text-color: var(--main-color)`).
diff --git a/articles/snippets/custom-file-download-names.md b/articles/snippets/custom-file-download-names.md
new file mode 100644
index 000000000..f350b72d8
--- /dev/null
+++ b/articles/snippets/custom-file-download-names.md
@@ -0,0 +1,17 @@
+---
+title: "Tip: Customize the names of downloadable files"
+shortTitle: Customize the names of downloadable files
+type: tip
+tags: [webdev,html,browser]
+author: chalarangelo
+cover: hard-disk
+excerpt: Learn what HTML5 attribute you can use to customize the names of your downloadable files with this quick tip.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+HTML5 introduced a variety of convenient features that many of us use every day. As downloadable links aren't something I work with very often, I recently found out that you can use the `download` attribute on an `
` element for much more than just making it trigger a download. In fact, you can pass it a string value that will act as the name of the downloadable file, effectively allowing you to customize its name:
+
+```html
+
+ June 2020
+```
diff --git a/articles/snippets/detect-caps-lock-is-on.md b/articles/snippets/detect-caps-lock-is-on.md
new file mode 100644
index 000000000..cada92994
--- /dev/null
+++ b/articles/snippets/detect-caps-lock-is-on.md
@@ -0,0 +1,36 @@
+---
+title: How can I detect if Caps Lock is on with JavaScript?
+shortTitle: Detect Caps Lock
+type: question
+tags: [javascript,browser,event]
+author: chalarangelo
+cover: keyboard
+excerpt: If you need to check if Caps Lock is on when the user is typing in the browser, JavaScript's got you covered.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Oftentimes, especially when creating password inputs, you need to check if the Caps Lock key is on and inform the user. You can do that using the [`KeyboardEvent.getModifierState()`](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState) method with a value of `'CapsLock'`. This means that you have to listen for a keyboard event on an element in order to check the state of the Caps Lock key:
+
+```html
+
+```
+
+```js
+const el = document.getElementById('password');
+const msg = document.getElementById('password-message');
+
+el.addEventListener('keyup', e => {
+ msg.style = e.getModifierState('CapsLock')
+ ? 'display: block'
+ : 'display: none';
+});
+```
+
+As you can see from the above example, the `'keyup'` event is used on our element of choice to then call `KeyboardEvent.getModifierState()` and determine the state of the `'CapsLock'` key. `'keydown'` and `'keypress'` might also work. However, after testing on multiple devices, it seems that using `'keyup'` is the preferred method as it works better across different OSes and browsers.
diff --git a/articles/snippets/dns-record-basics.md b/articles/snippets/dns-record-basics.md
new file mode 100644
index 000000000..9a90407dc
--- /dev/null
+++ b/articles/snippets/dns-record-basics.md
@@ -0,0 +1,25 @@
+---
+title: DNS Record Basics
+type: cheatsheet
+tags: [webdev,dns,server,cheatsheet]
+author: chalarangelo
+cover: sparkles
+excerpt: DNS records may not be a thing you work too often with. Regardless, some basic knowledge can go a long way.
+dateModified: 2022-01-09T05:00:00-04:00
+---
+
+Most web developers go about their day-to-day without having to deal with DNS records most of the time. Regardless, knowing what DNS stands for and the types of DNS records are pretty useful.
+
+### DNS Definition
+
+The Domain Name System (abbreviated to DNS), translates human-readable domain names (e.g www.google.com to machine-readable IP addresses (e.g. 142.250.186.46).
+
+### DNS Records
+
+A DNS is made up of multiple records of different types, each one with its own purpose. Here's a breakdown of the most commonly-used ones:
+
+- **A record**: The address record. Used to map a domain name to an IPv4 address. Similarly, the **AAAA record** is used to map a domain name to an IPv6 address.
+- **CNAME records**: A canonical name record. Creates an alias that points to another domain or subdomain, but never an IP address.
+- **ANAME record**: Allows you to point the root of your domain to a hostname or a domain name.
+- **TXT records**: Allow the addition of limited text notes and is often used for ownership verification purposes, validation or security.
+- **MX record**: Specifies the mail server responsible for accepting the incoming and outgoing emails for a domain. Should point to a mail server name, not an IP address.
diff --git a/articles/snippets/escaping-tutorial-hell.md b/articles/snippets/escaping-tutorial-hell.md
new file mode 100644
index 000000000..b756827a8
--- /dev/null
+++ b/articles/snippets/escaping-tutorial-hell.md
@@ -0,0 +1,39 @@
+---
+title: Escaping tutorial hell
+type: story
+tags: [career,webdev,programming,jobs]
+author: chalarangelo
+cover: campfire
+excerpt: Many beginners get stuck in tutorial hell without even realizing. Here are 4 simple ways to escape tutorial hell and get back to learning.
+dateModified: 2022-05-26T05:00:00-04:00
+---
+
+Tutorial hell refers to the stage in your learning journey, where you are following along with tutorials, not truly learning that much. Tutorials are by nature a curated experience. While that's not definitively bad, it's **not always the best way** to explore the landscape and familiarize with concepts and tools. Neither is it the best way to learn how to think for yourself. So how can you escape it?
+
+### Debug
+
+The most common exit ramp comes up when you end up in debugging mode. Oftentimes a tutorial can be outdated or something in the setup can be just a tiny bit different. At this point, you have to figure out how to solve the issue to proceed.
+
+Entering debugging mode, you realize that **you know only a part of the big picture**. What you don't know might not be immediately obvious, but with perseverance you will be able to figure it out. At that point, you can start looking for answers to solve the issue.
+
+Debugging a problem offers a little bit of **exposure to the underlying technologies and concepts**. This way you can dip your toe into whatever it is you are working with, without getting overwhelmed.
+
+### Be curious
+
+Curiosity killed the cat, but not you. Stop every step of the way to ask what it is you are learning. Do you understand the concepts? Do you know what it is you are building? Is this tool your only option? What problem does it solve? Are there others?
+
+Questions are a valuable tool to help you explore the landscape. You don't necessarily need to answer them all, nor do you need to read tons of documentation or articles about a topic. Simply **taking a peek at the big picture** and **asking questions** is enough. You can always come back later and dive deeper.
+
+### Experiment
+
+The third and best way to escape tutorial hell is to experiment. After you finish a couple of tutorials, **put your skills to the test**. Try to build something from scratch, looking up anything you need to, as you go. It won't be as easy or as fast as the tutorial was, but you'll learn a lot more.
+
+After you build a project, **take another look**. Figure out what you could have done differently or what parts of it you don't understand well enough. Refine it, polish up parts of it, add new features. The more time you put into it, the better you will become.
+
+Then do it a few more times and experiment with a few more ideas. As soon as you start working on your own projects and get into a rhythm, it's a lot easier to learn new things. Some slopes will be steeper and others will be more gentle. But you will feel much **more confident in your skills** than blindly following tutorials.
+
+### Learn your own way
+
+As a closing suggestion, I want to urge you to **find your own learning style**. Tutorials might be right for some and I don't suggest you dismiss them entirely. After all, we all have to start somewhere. But if they don't work for you, **mix it up a bit**. Try reading the documentation, solving coding exercises or tinkering with an existing project. Everyone is different and there's no one size fits all when it comes to learning.
+
+For some, much like myself, teaching is the best learning experience. After all, if you can't explain something simply, you probably don't understand it well enough. Explaining, then, can lead you to researching, debugging, experimenting and being curious all at once. And teaching, much like learning, can be done in many many different ways.
diff --git a/articles/snippets/eslint-refactor-for-in.md b/articles/snippets/eslint-refactor-for-in.md
new file mode 100644
index 000000000..b030b839a
--- /dev/null
+++ b/articles/snippets/eslint-refactor-for-in.md
@@ -0,0 +1,49 @@
+---
+title: "Tip: Refactoring your for...in loops to avoid ESLint warnings"
+shortTitle: Refactoring for...in loops to avoid ESLint warnings
+type: tip
+tags: [javascript,array,iterator,eslint]
+author: chalarangelo
+cover: typing
+excerpt: ESLint is a really useful tool, but sometimes it gets in the way. Learn how to refactor code to get rid of a common warning.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+ESLint is one of my tools of choice, but oftentimes it gets in the way of work, due to the way it prefers me to do things. One of the warnings I have seen more times than I care to admit is the following:
+
+> for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array.eslint(no-restricted-syntax)
+
+And here are three refactoring options to deal with it:
+
+### Object.keys()
+
+`Object.keys()` has the exact same behavior as a `for...in` loop, so it can be used as a drop-in replacement:
+
+```js
+const data = [3, 4];
+// Same as for (let k in data) console.log(k)
+Object.keys(data).forEach(k => console.log(k));
+// 0 1
+```
+
+### Object.values()
+
+`Object.values()` is very similar to `Object.keys()`, but returns the values instead of the keys, which might be what you are really using the keys for:
+
+```js
+const data = [3, 4];
+// Iterate over the values
+Object.values(data).forEach(v => console.log(v));
+// 3 4
+```
+
+### Object.entries()
+
+Finally, if you need both key and value, `Object.entries()` has you covered:
+
+```js
+const data = [3, 4];
+// Iterate over the data, returning key-value pairs
+Object.entries(data).forEach(e => console.log(e[0], e[1]));
+// [0, 3] [1, 4]
+```
diff --git a/articles/snippets/flexbox-cheatsheet.md b/articles/snippets/flexbox-cheatsheet.md
new file mode 100644
index 000000000..9e093c2be
--- /dev/null
+++ b/articles/snippets/flexbox-cheatsheet.md
@@ -0,0 +1,79 @@
+---
+title: Flexbox Cheat Sheet
+type: cheatsheet
+tags: [css,layout,flexbox,cheatsheet]
+author: chalarangelo
+cover: frames
+excerpt: Flexbox allows you to create fluid layouts easily. If you are constantly looking up how it works, this handy cheatsheet is all you need.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Container
+
+- `display: flex` or `display: inline-flex`: creates a flex context (or an inline flex context) for direct children of this element
+- `flex-direction` determines the main and cross axis for the container, valid values are:
+ - `row` (default): horizontal, in the direction of writing (left to right for English)
+ - `row-reverse`: horizontal, in the opposite direction of writing (right to left for English)
+ - `column`: vertical, top to bottom
+ - `column-reverse`: vertical, bottom to top
+- `flex-wrap` determines if flex items will try to fit in one line, valid values are:
+ - `nowrap` (default): all flex items will be on one line
+ - `wrap`: flex items will wrap onto multiple lines, top to bottom
+ - `wrap-reverse`: flex items will wrap onto multiple lines, bottom to top
+- `flex-flow`: shorthand combining `flex-direction` and `flex-wrap`
+ - Formal syntax: `flex-flow: <'flex-direction'> || <'flex-wrap'>`
+- `justify-content` defines the alignment along the main axis, valid values are:
+ - `flex-start` (default): pack flex items from the start
+ - `flex-end`: pack flex items from the end
+ - `start`: pack items from the start
+ - `end`: pack items from the end
+ - `left`: pack items from the left
+ - `right`: pack items from the right
+ - `center`: pack items around the center
+ - `space-around`: distribute items evenly with equal space around them
+ - `space-between`: distribute items evenly with equal space between them
+ - `space-evenly`: distribute items evenly, ensuring equal space between any two items
+ - `stretch`: distribute items evenly, stretching auto-sized items to fit the container
+- `align-items` defines the alignment along the cross axis, valid values are:
+ - `flex-start` (default): pack flex items from the start
+ - `flex-end`: pack flex items from the end
+ - `start`: pack items from the start
+ - `end`: pack items from the end
+ - `center`: pack items around the center
+ - `baseline`: align items based on their baselines
+ - `stretch`: stretch items to fill the container
+- `align-content` defines the alignment of extra space along the cross axis, valid values are:
+ - `flex-start` (default): pack flex items from the start
+ - `flex-end`: pack flex items from the end
+ - `start`: pack items from the start
+ - `end`: pack items from the end
+ - `center`: pack items around the center
+ - `space-around`: distribute items evenly with equal space around them
+ - `space-between`: distribute items evenly with equal space between them
+ - `space-evenly`: distribute items evenly, ensuring equal space between any two items
+ - `stretch`: distribute items evenly, stretching auto-sized items to fit the container
+
+
+
+### Items
+
+- `flex-grow` determines how much the item can grow if necessary
+ - Accepts a single positive number (unitless), default value is `0`
+ - Specifies how much of the remaining space in the flex container should be assigned to the item
+ - The remaining space is the size of the flex container minus the size of all flex items' sizes together
+ - If all items have the same `flex-grow`, all items will receive an equal share of the remaining space
+ - If not all items have the same `flex-grow`, the remaining space is distributed according to the ratio defined by these values
+- `flex-shrink` determines how much the items can shrink if necessary
+ - Accepts a single positive number (unitless), default value is `1`
+ - If the size of all flex items is larger than the flex container, items shrink to fit according to `flex-shrink`
+- `flex-basis` determines the initial size of a flex item before the remaining space is distributed
+ - Can use any valid `width` value, intrinsic size values, `auto` (default) or `content`
+ - `auto` means "look at my `width` or `height` property", whereas `content` is used for automatic sizing
+- `flex`: shorthand combining `flex-grow`, `flex-shrink` and `flex-basis`
+ - Formal syntax: `flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]`
+- `align-self` allows the item to override the default `align-items` specified by the container
+ - Valid values are the same as those of the `align-items` property in the container
+- `order` determines the ordering of the item
+ - Accepts an integer value
+ - Items in a container are sorted by ascending `order` value and then by their source code order
+ - Might cause accessibility issues if used incorrectly
diff --git a/articles/snippets/git-aliases.md b/articles/snippets/git-aliases.md
new file mode 100644
index 000000000..170bd02dd
--- /dev/null
+++ b/articles/snippets/git-aliases.md
@@ -0,0 +1,51 @@
+---
+title: Git aliases
+type: cheatsheet
+tags: [git,configuration,cheatsheet]
+author: chalarangelo
+cover: organizer
+excerpt: Increase your productivity by creating aliases for many common git operations.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Creating aliases
+
+Use the command below to create aliases, replacing `
` with the name of the alias and `` with the command to be aliased:
+
+```shell
+git config --global alias.
+```
+
+Additionally, you can use [edit the configuration file](/git/s/edit-config) and add many aliases all at once.
+
+### Useful aliases
+
+```editorconfig
+[alias]
+ co = checkout
+ cob = checkout -b
+ coo = !git fetch && git checkout
+ br = branch
+ brd = branch -d
+ st = status
+ aa = add -A .
+ unstage = reset --soft HEAD^
+ cm = commit -m
+ amend = commit --amend -m
+ fix = commit --fixup
+ undo = reset HEAD~1
+ rv = revert
+ cp = cherry-pick
+ pu = !git push origin `git branch --show-current`
+ fush = push -f
+ mg = merge --no-ff
+ rb = rebase
+ rbc = rebase --continue
+ rba = rebase --abort
+ rbs = rebase --skip
+ rom = !git fetch && git rebase -i origin/master --autosquash
+ save = stash push
+ pop = stash pop
+ apply = stash apply
+ rl = reflog
+```
diff --git a/articles/snippets/git-commit-different-date.md b/articles/snippets/git-commit-different-date.md
new file mode 100644
index 000000000..b79c01bc8
--- /dev/null
+++ b/articles/snippets/git-commit-different-date.md
@@ -0,0 +1,20 @@
+---
+title: "Tip: Create a commit with a different date"
+shortTitle: Create a commit with a different date
+type: tip
+tags: [git,commit]
+author: chalarangelo
+cover: ice
+excerpt: Ever needed to create a git commit with a different date? Here's a quick and easy way to do it.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Sometimes, you might run into a situation where you need to create a commit with a different date than the current one. Luckily, you can handle this using `GIT_AUTHOR_DATE` and `GIT_COMMITTER_DATE`:
+
+```shell
+GIT_AUTHOR_DATE='Mon May 18 19:32:10 2020 -0400' \
+ GIT_COMMITTER_DATE='Mon May 18 19:32:10 2020 -0400'\
+ git commit -m 'Commit from the past'
+```
+
+As shown in the example above, you can set both values to any date you like and your code will be committed on that date. Note that the format for the values above is `'date +"%s %z"'`, also referred to as internal raw git format, but you can also use other formats, such as RFC 2822 (`'Mon, 18 May 2020 19:32:10 -0400'`), ISO 8601 (`'2020-05-18 19:32:10 -0400'`), local (`'Mon May 18 19:32:10 2020'`), short (`'2020-05-18'`) or relative (`5.seconds.ago`, `2.years.3.months.ago`, `'6am yesterday'`).
diff --git a/articles/snippets/git-fast-forward.md b/articles/snippets/git-fast-forward.md
new file mode 100644
index 000000000..758429b65
--- /dev/null
+++ b/articles/snippets/git-fast-forward.md
@@ -0,0 +1,24 @@
+---
+title: How does Git's fast-forward mode work?
+shortTitle: Git fast-forward
+type: question
+tags: [git,branch]
+author: chalarangelo
+cover: boats
+excerpt: Learn about Git's fast-forward mode works and its benefits when mergin branches, so you can decide if it's a good fit for you and your team.
+dateModified: 2021-07-15T05:00:00-04:00
+---
+
+Merging a branch is one of the most common operations when working with Git. Depending on your team and projects you've been a part of, you might have heard of or even used Git's **fast-forward** mode when merging. Fast-forward mode is the default in Git, however GitHub will essentially override this by default and create a merge commit instead.
+
+
+
+### Fast-forward merge
+
+As stated above, Git's default is to use fast-forward merge. It will take the commits from the branch being merged and place them at the tip of the branch you're merging into. This creates a **linear history**, which is also the main advantage of using fast-forward merge. If you want to emulate fast-forward merge on GitHub, you can use the "Rebase and merge" option.
+
+### Non fast-forward merge
+
+GitHub, on the other hand, uses non fast-forward merge by default. It will create a merge commit at the tip of the branch you're merging into, optionally referencing the branch being merged in the commit message. This has the advantage of **keeping track of branches** more explicitly than fast-forward merge. If you want to get the same behavior in a Git terminal, you can use the `--no-ff` flag.
+
+As a side note, you can configure the default Git merge behavior, using `git config`. To learn how to do so, you can take a look at the [relevant snippet](/git/s/disable-fast-forward).
diff --git a/articles/snippets/github-co-authors.md b/articles/snippets/github-co-authors.md
new file mode 100644
index 000000000..74e860755
--- /dev/null
+++ b/articles/snippets/github-co-authors.md
@@ -0,0 +1,26 @@
+---
+title: "Tip: How to add multiple authors to a commit"
+shortTitle: Add multiple authors to a commit
+type: tip
+tags: [git,github,programming,webdev]
+author: chalarangelo
+cover: book-chair
+excerpt: Learn how to add multiple authors to a git commit with this quick and easy tip.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+You can add multiple authors to a git commit, by adding one or more `Co-authored-by` trailers to the commit's message:
+
+```shellsession
+$ git commit -m "Refactor usability tests.
+>
+>
+Co-authored-by: name
+Co-authored-by: another-name "
+```
+
+### Notes:
+
+- To correctly attribute a commit to a co-author, you must use the email associated with their GitHub account.
+- If a person's email is private, you can use their GitHub-provided `no-reply` email.
+- Leave one or preferably two empty lines before any `Co-authored-by` trailers.
diff --git a/articles/snippets/html-head-icons.md b/articles/snippets/html-head-icons.md
new file mode 100644
index 000000000..1039100f2
--- /dev/null
+++ b/articles/snippets/html-head-icons.md
@@ -0,0 +1,22 @@
+---
+title: Recommended HTML head icon tags
+shortTitle: HTML favicons template
+type: story
+tags: [webdev,html,browser]
+author: chalarangelo
+cover: boutique-home-office-3
+excerpt: Ensure your HTML documents have a proper favicon by including these lines in your `` element.
+dateModified: 2023-01-24T05:00:00-04:00
+---
+
+Over the years, I've seen many different and often conflicting guidelines about favicons and which tags are essential. Nowadays, I think you can get away with a very **minimal set of meta tags** and tailor them to your needs as you go. Here's my recommendation for the bare minimum you should include in your `` element:
+
+```html
+
+
+
+
+
+```
+
+By creating a single 192x192 PNG asset, you can cover almost all modern devices and browsers, without too much hassle. If you want to go the extra mile, you can include a few more quite easily. Simply downscale the image and include more `rel="icon"` meta tags with different `sizes` attributes.
diff --git a/articles/snippets/html-head-links.md b/articles/snippets/html-head-links.md
new file mode 100644
index 000000000..84be62111
--- /dev/null
+++ b/articles/snippets/html-head-links.md
@@ -0,0 +1,26 @@
+---
+title: Recommended HTML head links
+shortTitle: HTML head links template
+type: story
+tags: [webdev,html,browser]
+author: chalarangelo
+cover: boutique-home-office-4
+excerpt: Make your HTML documents more SEO-friendly by including these lines in your `` element.
+dateModified: 2023-01-26T05:00:00-04:00
+---
+
+The `` element of an HTML document is where you can include links to external resources such as CSS stylesheets and JavaScript files. Some ` ` elements, however, are important for SEO and metadata purposes. Here's a list of a few really important ones I like to include:
+
+```html
+
+
+
+
+
+
+```
+
+- The `canonical` link element tells search engines which URL is the **canonical version** of the page. This helps prevent duplicate content issues and ensures that the correct page is indexed.
+- The `sitemap` link element tells search engines where to find the **sitemap** for the website. Sitemaps are XML files that contain a list of all the pages on the website and their metadata. They are used by search engines to index the website and display it in search results.
+- The `alternate` link element tells search engines where to find the **RSS feed** for the website. RSS feeds are XML files that contain a list of the most recent posts on the website. They are used by search engines to display the website's content in search results, as well as by RSS readers to display the website's content in a more convenient format.
+- The `search` link element is used by browsers to display a **search box** in the browser's address bar. This allows users to search the website directly from the address bar, instead of having to navigate to the search page.
diff --git a/articles/snippets/html-head-social-tags.md b/articles/snippets/html-head-social-tags.md
new file mode 100644
index 000000000..7e9ae9d27
--- /dev/null
+++ b/articles/snippets/html-head-social-tags.md
@@ -0,0 +1,37 @@
+---
+title: Recommended social tags for HTML head
+shortTitle: HTML social tags template
+type: story
+tags: [webdev,html,browser]
+author: chalarangelo
+cover: boutique-home-office-2
+excerpt: Ensure your HTML documents can be shared on social media by including these lines in your `` element.
+dateModified: 2023-01-22T05:00:00-04:00
+---
+
+Social media play an important role to any content's success. To ensure your content is properly shared on social media, you should include some essential tags in your `` element:
+
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+The above snippet contains OpenGraph and Twitter tags. **OpenGraph tags** are used by Facebook and other social media platforms to display a preview of the page when it's shared. Similarly, Twitter uses **Twitter tags** for the same information. Here's a breakdown of each one:
+
+- The `og:title` and `twitter:title` meta tags are used to display the page's title in the preview.
+- The `og:description` and `twitter:description` meta tags are used to display a short description of the page in the preview.
+- The `og:image` and `twitter:image` meta tags are used to display an image in the preview.
+- The `og:site_name` meta tag is used to display the name of the site in the preview.
+- The `og:url` meta tag is used to display the URL of the page in the preview.
+- The `twitter:card` meta tag is used to display a preview of the page when it's shared. Available values are `summary`, `summary_large_image`, `app` and `player`.
+- The `twitter:site` meta tag is used to display the Twitter handle of the site in the preview.
diff --git a/articles/snippets/html-recommended-minimum-head.md b/articles/snippets/html-recommended-minimum-head.md
new file mode 100644
index 000000000..e063ed029
--- /dev/null
+++ b/articles/snippets/html-recommended-minimum-head.md
@@ -0,0 +1,28 @@
+---
+title: Recommended minimum HTML head
+shortTitle: HTML head template
+type: story
+tags: [webdev,html,browser]
+author: chalarangelo
+cover: boutique-home-office-1
+excerpt: Ensure your HTML documents are properly structured by including these lines in your `` element.
+dateModified: 2023-01-18T05:00:00-04:00
+---
+
+An essential part of an HTML document is the `` element, which contains metadata about the document. Some vital information, such as the document's title and character encoding are stored in the `` element. It's also where you can include links to external resources such as CSS stylesheets and JavaScript files.
+
+More often than not, this sort of metadata can grow in complexity with time. However, there are a few important things that should never be omitted. Here's a list of the bare minimum you should include in your `` element:
+
+```html
+
+
+
+ Page Title
+
+
+```
+
+- The `charset` meta tag tells the browser what **character encoding** to use when rendering the document.
+- The `viewport` meta tag tells the browser how to render the page on **mobile devices**.
+- The `title` element is used by search engines to display the page's **title** in search results.
+- The `description` meta tag is used by search engines to display a **short description** of the page in search results.
diff --git a/articles/snippets/http-status-codes-cheatsheet.md b/articles/snippets/http-status-codes-cheatsheet.md
new file mode 100644
index 000000000..e7bdd3120
--- /dev/null
+++ b/articles/snippets/http-status-codes-cheatsheet.md
@@ -0,0 +1,40 @@
+---
+title: Common HTTP status codes Cheat Sheet
+shortTitle: HTTP status codes
+type: cheatsheet
+tags: [webdev,http]
+author: chalarangelo
+cover: lake-runner
+excerpt: Familiarize yourself with the most common HTTP status codes with this handy cheatsheet.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### 1xx - Informational
+
+- **100**: Continue - Everything is ok so far
+- **102**: Processing - Request is being processed, no response available yet
+
+### 2xx - Success
+
+- **200**: OK - Request successful
+- **201**: Created - Request fulfilled, new resource has been created
+
+### 3xx - Redirection
+
+- **301**: Moved Permanently - Resource permanently moved to a new URL
+- **302**: Moved Temporarily - Resource temporarily moved to a new URL
+
+### 4xx - Client Error
+
+- **400**: Bad Request - Server cannot understand and process the request
+- **401**: Unauthorized - Authentication required, user not yet authenticated
+- **403**: Forbidden - Insufficient access permissions to the resource
+- **404**: Not Found - Requested resource not found
+- **410**: Gone - Request no longer available due to intentional removal
+
+### 5xx - Server Error
+
+- **500**: Internal Server Error - Generic unhandled server error
+- **502**: Bad Gateway - Gateway server got an invalid response
+- **503**: Service Unavailable - Server temporarily unable to handle request
+- **504**: Gateway Timeout - Gateway server didn't get a response in time
diff --git a/articles/snippets/javascript-add-key-value-pair-to-object.md b/articles/snippets/javascript-add-key-value-pair-to-object.md
new file mode 100644
index 000000000..923382acf
--- /dev/null
+++ b/articles/snippets/javascript-add-key-value-pair-to-object.md
@@ -0,0 +1,77 @@
+---
+title: How can I add a key-value pair to a JavaScript object?
+shortTitle: Add key-value pair to object
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: pineapple-laptop
+excerpt: Adding a key-value pair to a JavaScript object is straightforward, yet there are multiple ways available to do so.
+dateModified: 2022-07-21T05:00:00-04:00
+---
+
+Adding a key-value pair to a JavaScript object is straightforward, yet there are multiple ways available to do so. While mostly similar, these approaches have some differences that you should be aware of.
+
+### Dot notation
+
+The most common and straightforward way to add a key-value pair to an object is to use the dot notation. You have probably already used this in the past, and it's sufficient in most situations you will encounter.
+
+```js
+const obj = { a: 1 };
+obj.b = 2;
+obj.c = 3;
+// obj = { a: 1, b: 2, c: 3 }
+```
+
+### Square bracket notation
+
+Similar to dot notation, square bracket notation comes in handy when dealing with **dynamic keys**, but can also work with static keys. Apart from that, it's exactly the same as dot notation both in functionality and performance.
+
+```js
+const obj = { a: 1 };
+const bKey = 'b';
+obj[bKey] = 2;
+obj['c'] = 3;
+// obj = { a: 1, b: 2, c: 3 }
+```
+
+### Object.assign()
+
+`Object.assign()` is slightly different than the previous two options. It can be used to add multiple properties to an object at once and it can also **shallow merge** two or more objects. It is not as performant, however, so it should only be used when necessary.
+
+```js
+const obj = { a: 1 };
+Object.assign(obj, { b: 2 }, { c: 3 });
+// obj = { a: 1, b: 2, c: 3 }
+```
+
+### Object.defineProperty()
+
+Another, less-common, way to add a key-value pair to an object is to use `Object.defineProperty()`. This is the lest performant way to add a key-value pair to an object, but it allows the new property to be **precisely defined**. This function accepts either a data or accessor descriptor as its second argument, allowing the behavior of the new property to be customized as desired. Bear in mind that you can add multiple properties at once, using `Object.defineProperties()`.
+
+```js
+const obj = { a: 1 };
+Object.defineProperty(obj, 'b', {
+ value: 2,
+ enumerable: true,
+ configurable: true,
+ writable: true
+});
+Object.defineProperty(obj, 'c', {
+ value: 3,
+ enumerable: true,
+ configurable: true,
+ writable: true
+});
+// obj = { a: 1, b: 2, c: 3 }
+```
+
+### Object spread operator
+
+Last but not least, there's the object spread operator (`...`). Contrary to previous methods, this one **doesn't mutate the original object**, but instead returns a new object with the added properties. As expected, the performance of this approach is significantly worse than previous ones, due to the need to create a new object.
+
+```js
+const obj = { a: 1 };
+const newObj = { ...obj, b: 2, c: 3 };
+// obj = { a: 1 }
+// newObj = { a: 1, b: 2, c: 3 }
+```
diff --git a/articles/snippets/javascript-array-comparison.md b/articles/snippets/javascript-array-comparison.md
new file mode 100644
index 000000000..ff9cc1608
--- /dev/null
+++ b/articles/snippets/javascript-array-comparison.md
@@ -0,0 +1,88 @@
+---
+title: How do I compare two arrays in JavaScript?
+shortTitle: JavaScript array comparison
+type: question
+tags: [javascript,array,comparison]
+author: chalarangelo
+cover: coconuts
+excerpt: Learn how you can compare two arrays in JavaScript using various different techniques.
+dateModified: 2021-09-27T16:36:32+03:00
+---
+
+### Equality comparison
+
+Comparing two arrays in JavaScript using either the loose or strict equality operators (`==` or `===`) will most often result in `false`, even if the two arrays contain the same elements in the same order. This is due to the fact that arrays and objects are compared by reference and not by value in JavaScript, which means this solution does not produce the desired result:
+
+```js
+const a = [1, 2, 3];
+const b = [1, 2, 3];
+
+a === b; // false
+```
+
+### JSON.stringify
+
+A common solution that many people suggest is to use `JSON.stringify()`. This allows us to serialize each array and then compare the two serialized strings. A simple implementation of this might look something like this:
+
+```js
+const equals = (a, b) => JSON.stringify(a) === JSON.stringify(b);
+
+const a = [1, 2, 3];
+const b = [1, 2, 3];
+
+equals(a, b); // true
+```
+
+While this seems like a great, short and easily understandable solution, it falls short on some edge cases where different values' serialized string is the same. For example:
+
+```js
+const str = 'a';
+const strObj = new String('a');
+str === strObj; // false
+equals([str], [strObj]); // true, should be false
+
+null === undefined; // false
+equals([null], [undefined]); // true, should be false
+```
+
+While these cases seem rather uncommon, they might cause some very annoying issues that are hard to track down and fix. This is the reason why this solution is not recommended for most use-cases.
+
+### A better way
+
+A better approach would be to compare the two arrays' `length`s and use `Array.prototype.every()` to compare the values of the two:
+
+```js
+const equals = (a, b) =>
+ a.length === b.length &&
+ a.every((v, i) => v === b[i]);
+
+const a = [1, 2, 3];
+const b = [1, 2, 3];
+const str = 'a';
+const strObj = new String('a');
+
+equals(a, b); // true
+equals([str], [strObj]); // false
+equals([null], [undefined]); // false
+```
+
+This approach safeguards against the serialization issue described above. However it does not take into account nested arrays or objects, which need to be checked recursively. For a robust solution that handles this and other issues, you should use the [equals snippet](/js/s/equals).
+
+### Comparing out of order
+
+Finally, there are cases where the order of the elements in each array is not important and we only care about the same values existing in both arrays. For these cases, you can use `Set` and `Array.prototype.filter()` in combination with a loop to iterate over unique values and check if each one appears the same amount of times in each array:
+
+```js
+const equalsIgnoreOrder = (a, b) => {
+ if (a.length !== b.length) return false;
+ const uniqueValues = new Set([...a, ...b]);
+ for (const v of uniqueValues) {
+ const aCount = a.filter(e => e === v).length;
+ const bCount = b.filter(e => e === v).length;
+ if (aCount !== bCount) return false;
+ }
+ return true;
+}
+```
+
+For a more detailed explanation, you should check out the [haveSameContents snippet](/js/s/have-same-contents).
diff --git a/articles/snippets/javascript-array-includes-value.md b/articles/snippets/javascript-array-includes-value.md
new file mode 100644
index 000000000..5e1cc5d55
--- /dev/null
+++ b/articles/snippets/javascript-array-includes-value.md
@@ -0,0 +1,37 @@
+---
+title: How can I check if a JavaScript array includes a specific value?
+shortTitle: JavaScript array includes value
+type: question
+tags: [javascript,array]
+author: chalarangelo
+cover: bridge-drop
+excerpt: Checking if an array includes a specific value is pretty straightforward, except when it comes to objects.
+dateModified: 2022-09-18T05:00:00-04:00
+---
+
+### Primitive values
+
+You can use `Array.prototype.includes()` to check if an array contains a primitive value. This is the most convenient option when working with strings, numbers, booleans, symbols, `null` or `undefined`. You can even specify an index as a secondary parameter to start searching from.
+
+```js
+const array = [1, 2, 3, 4, 5];
+
+array.includes(3); // true
+array.includes(6); // false
+array.includes(3, 3); // false
+```
+
+### Objects
+
+Unlike primitive values, you can't use `Array.prototype.includes()` to check if an array includes an object. This comes down to how JavaScript compares values and the fact that [objects are reference types](/articles/s/javascript-pass-by-reference-or-pass-by-value). I highly recommend reading the previous article about [object comparison](/articles/s/javascript-object-comparison), as I won't be going into detail on how to compare objects here.
+
+Due to this difference between primitive values and objects, you can't use `Array.prototype.includes()` to check if an array includes an object. However, provided you implement a [deep equality function](/js/s/equals), you can use `Array.prototype.some()` to check if any object matches the shape of another object.
+
+```js
+const array = [{ a: 1 }, { a: 2 }, { a: 3 }];
+
+const equals = (a, b) => Object.keys(a).every(key => a[key] === b[key]);
+
+array.some(item => equals(item, { a: 2 })); // true
+array.some(item => equals(item, { a: 4 })); // false
+```
diff --git a/articles/snippets/javascript-arrow-function-event-listeners.md b/articles/snippets/javascript-arrow-function-event-listeners.md
new file mode 100644
index 000000000..ffbbb2775
--- /dev/null
+++ b/articles/snippets/javascript-arrow-function-event-listeners.md
@@ -0,0 +1,58 @@
+---
+title: Can I use an arrow function as the callback for an event listener in JavaScript?
+shortTitle: Arrow function as callback for event listener
+type: question
+tags: [javascript,browser,event,function]
+author: chalarangelo
+cover: coffee-float
+excerpt: Learn the differences between JavaScript ES6 arrow functions and regular functions and how they affect event listener callbacks.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Arrow functions
+
+JavaScript ES6 introduced the concept of arrow functions, a new way to define and write functions. While they might seem like a syntactic sugar on top of regular functions, they have a key difference which lies in the way the `this` context is bound. I strongly suggest you read [Understanding the "this" keyword in JavaScript](/blog/s/javascript-this), as I will not go into detail about the topic in this article. To summarize:
+
+> Arrow functions do not have their own bindings for `this`, resulting in `this` retaining the value of the enclosing lexical context's `this`.
+
+### Event listener callbacks
+
+A common task when writing browser-side JavaScript is creating event listeners. For example:
+
+```js
+const toggleElements = document.querySelectorAll('.toggle');
+toggleElements.forEach(el => {
+ el.addEventListener('click', function() {
+ this.classList.toggle('active');
+ });
+});
+```
+
+In the example above, we use `NodeList.prototype.forEach()` to iterate over matching nodes and `EventTarget.addEventListener()` with a regular function as the callback for the `'click'` event to swap between an active and inactive state for the clicked element. We are using a regular function, so the `this` context inside the callback will be bound to the event target.
+
+### Arrow functions as callbacks
+
+As we have already explained, arrow functions do not have their own bindings for `this`. So what happens if we convert the previous code snippet's callback to an arrow function? Its `this` context refers to the global one, which in this case is the `Window` object.
+
+```js
+const toggleElements = document.querySelectorAll('.toggle');
+toggleElements.forEach(el => {
+ el.addEventListener('click', () => {
+ this.classList.toggle('active'); // `this` refers to `Window`
+ // Error: Cannot read property 'toggle' of undefined
+ });
+});
+```
+
+This code will fire the event listener and execute the callback anytime the matching element is clicked. It will, however, throw an error, due to the `Window` object not having a `classList` property. Oftentimes, the code could even fail silently. An example would be a condition that always evaluates to `false` for `Window`, but could evaluate to `true` for a given element. Issues like that result in many headaches and wasted hours until you can uncover and fix them.
+
+To deal with this, one could simply use the first argument of the callback function and `Event.target` or `Event.currentTarget` depending on their needs:
+
+```js
+const toggleElements = document.querySelectorAll('.toggle');
+toggleElements.forEach(el => {
+ el.addEventListener('click', (e) => {
+ e.currentTarget.classList.toggle('active'); // works correctly
+ });
+});
+```
diff --git a/articles/snippets/javascript-arrow-functions.md b/articles/snippets/javascript-arrow-functions.md
new file mode 100644
index 000000000..4831437bd
--- /dev/null
+++ b/articles/snippets/javascript-arrow-functions.md
@@ -0,0 +1,108 @@
+---
+title: Introduction to arrow functions in JavaScript
+shortTitle: Arrow functions introduction
+type: story
+tags: [javascript,function]
+author: chalarangelo
+cover: arrow-functions
+excerpt: JavaScript arrow functions are a very useful tool to learn and master. Here's a complete introduction to everything you need to know.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Syntax
+
+In order to understand arrow function syntax, we should start by refactoring a regular function step by step:
+
+```js
+function square(a) {
+ return a * a;
+}
+```
+
+We can start by refactoring the function declaration to use a variable assignment:
+
+```js
+const square = function (a) {
+ return a * a;
+}
+```
+
+Then, we can refactor the regular `function` to an arrow function:
+
+```js
+const square = (a) => {
+ return a * a;
+}
+```
+
+If there's only one argument, we can omit the parentheses around it:
+
+```js
+const square = a => {
+ return a * a;
+}
+```
+
+If the function is a single expression, you can omit the curly braces and `return` statement and use an implicit return:
+
+```js
+const square = a => a * a;
+```
+
+### Execution context
+
+The main difference between arrow functions and regular functions is execution context (i.e. the value of `this`). Technically speaking, most other differences often mentioned either stem from this one or are side effects of it.
+
+In a regular function, `this` is dynamic and depends on how the function was invoked:
+
+```js
+function simple() { return this; }
+const object = {
+ method() { return this; }
+};
+class Class {
+ classMethod() { console.log(this); }
+}
+const instance = new Class();
+
+simple(); // `this` refers to the global object
+new simple(); // `this` refers to the newly created instance
+
+object.method(); // `this` refers to `object`
+simple.call(object); // `this` refers to `object`
+
+instance.classMethod(); // `this` refers to `instance`
+setTimeout(
+ instance.classMethod, 0 // `this` refers to the global object
+);
+```
+
+Arrow functions, unlike regular ones, don't define their own execution context therefore `this` inside an arrow function always refers to the lexical `this` (i.e. the scope in which the arrow function was defined).
+
+```js
+const simple = () => this;
+const object = {
+ method: () => this
+};
+class Class {
+ classMethod = () => { console.log(this); }
+}
+const instance = new Class();
+
+simple(); // `this` refers to the global object
+new simple(); // Uncaught TypeError: simple is not a constructor
+
+object.method(); // `this` refers to the global object
+simple.call(object); // `this` refers to the global object
+
+instance.classMethod(); // `this` refers to `instance`
+setTimeout(
+ instance.classMethod, 0 // `this` refers to `instance`
+);
+```
+
+As you can see from these examples, there's a difference in how constructors work due to the execution context and how it's resolved. Regular functions can be used as constructors in contrast to arrow functions which will throw a `TypeError` instead.
+
+Moreover, arrow functions and regular functions present some differences when used to define class methods. A regular function method will end up with a different execution context when passed as a callback. This can be handled using `Function.prototype.bind()` or by using an arrow function which doesn't have this issue.
+
+If you want to read more about the `this` keyword, you should check out our [previous article on the subject](/blog/s/javascript-this).
diff --git a/articles/snippets/javascript-arrow-regular-function-differences.md b/articles/snippets/javascript-arrow-regular-function-differences.md
new file mode 100644
index 000000000..b6b00e820
--- /dev/null
+++ b/articles/snippets/javascript-arrow-regular-function-differences.md
@@ -0,0 +1,124 @@
+---
+title: What are the differences between arrow functions and regular functions in JavaScript?
+shortTitle: Arrow functions vs regular functions
+type: question
+tags: [javascript,function]
+author: chalarangelo
+cover: fallen-leaves
+excerpt: JavaScript's arrow functions are seemingly the same as regular functions, but there are some important differences you need to know.
+dateModified: 2021-10-17T05:00:00-04:00
+---
+
+JavaScript's arrow functions might seem the same as regular functions on the surface, but they have some very important differences:
+
+- Syntactical differences
+- `this` value (execution context)
+- Usage as methods
+- Usage as constructors
+- `arguments` binding
+
+### Syntax
+
+The first and most obvious difference between arrow functions and regular functions is their syntax. Not only do they look different, but arrow functions also provide an implicit return shorthand and allow parenthesis around a single argument to be omitted.
+
+```js
+const square = a => a * a;
+
+// Equivalent regular function
+function square(a) {
+ return a * a;
+}
+```
+
+### Execution context
+
+Inside a regular function, execution context (i.e. the value of `this`) is dynamic. This means that the value of `this` depends on how the function was invoked (simple invocation, method invocation, indirect invocation or constructor invocation). On the other hand, an arrow function does not define its own execution context. This results in an arrow function's `this` being resolved lexically (i.e. the scope in which the arrow function was defined).
+
+```js
+function logThis() {
+ console.log(this);
+}
+document.addEventListener('click', logThis);
+// `this` refers to the document
+
+const logThisArrow = () => {
+ console.log(this);
+};
+document.addEventListener('click', logThisArrow);
+// `this` refers to the global object
+```
+
+`Function.prototype.call()`, `Function.prototype.bind()` and `Function.prototype.apply()` do not work correctly with arrow functions either. Their purpose is to allow methods to execute within different scopes, but the `this` value of an arrow function cannot be changed, as it's resolved lexically.
+
+```js
+function logThis() {
+ console.log(this);
+}
+logThis.call(42); // Logs: 42
+
+const logThisArrow = () => {
+ console.log(this);
+};
+logThisArrow.call(42); // Logs the global object
+```
+
+### Methods
+
+Due to arrow functions not defining their own execution context, they're not well-suited for usage as methods. However, thanks to the [Class fields proposal](https://github.com/tc39/proposal-class-fields), arrow functions can be used as methods inside classes, if your environment supports it.
+
+```js
+const obj = {
+ x: 42,
+ logThisX: function() {
+ console.log(this.x, this);
+ },
+ logThisXArrow: () => {
+ console.log(this.x, this);
+ }
+};
+
+obj.logThisX(); // Logs: 42, Object {...}
+obj.logThisXArrow(); // Logs: undefined, the global object
+```
+
+### Constructors
+
+Regular functions can be used as constructors, using the `new` keyword. Yet another consequence of the lexical resolution of `this` inside arrow functions is that they cannot be used as constructors. Using `new` with an arrow function results in a `TypeError`.
+
+```js
+function Foo(bar) {
+ this.bar = bar;
+}
+const a = new Foo(42); // Foo {bar: 42}
+
+const Bar = foo => {
+ this.foo = foo;
+};
+const b = new Bar(42); // TypeError: Bar is not a constructor
+```
+
+### Arguments
+
+Another difference is the binding of the `arguments` object. Unlike regular functions, arrow functions don't have their own `arguments` object. A modern alternative that circumvents this limitation is the usage of rest parameters.
+
+```js
+function sum() {
+ return arguments[0] + arguments[1];
+};
+sum(4, 6); // 10
+
+const arguments = [1, 2, 3];
+const sumArrow = () => {
+ return arguments[0] + arguments[1];
+};
+sumArrow(4, 6); // 3 (resolves to 1 + 2)
+
+const sumRest = (...arguments) => {
+ return arguments[0] + arguments[1];
+}
+sumRest(4, 6); // 10
+```
+
+### Other differences
+
+Finally, there are a couple of other differences that are not as important, but worth mentioning. These include the lack of a `prototype` property in arrow functions, as well as the fact that the `yield` keyword may not be used in an arrow function's body. A consequence of the latter is that arrow functions cannot be used as generators.
diff --git a/articles/snippets/javascript-async-array-loops.md b/articles/snippets/javascript-async-array-loops.md
new file mode 100644
index 000000000..cc96dd4d8
--- /dev/null
+++ b/articles/snippets/javascript-async-array-loops.md
@@ -0,0 +1,93 @@
+---
+title: Asynchronous array loops in JavaScript
+shortTitle: Asynchronous array loops
+type: story
+tags: [javascript,array,function,promise]
+author: chalarangelo
+cover: sunflowers
+excerpt: Asynchronously looping over arrays in JavaScript comes with a few caveats you should watch out for.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Asynchronous operations seem to trip up a lot of developers. This is especially true when combined with looping over arrays, as there are some caveats that come with each option available.
+
+### For loops
+
+Combining `async` with a `for` (or a `for...of`) loop is possibly the most straightforward option when performing asynchronous operations over array elements. Using `await` inside a `for` loop will cause the code to stop and wait for the asynchronous operation to complete before continuing. This means that all promises will be run sequentially.
+
+```js
+const asyncUppercase = item =>
+ new Promise(resolve =>
+ setTimeout(
+ () => resolve(item.toUpperCase()),
+ Math.floor(Math.random() * 1000)
+ )
+ );
+
+const uppercaseItems = async () => {
+ const items = ['a', 'b', 'c'];
+ for (item of items) {
+ const uppercaseItem = await asyncUppercase(item);
+ console.log(uppercaseItem);
+ }
+
+ console.log('Items processed');
+};
+
+uppercaseItems();
+// LOGS: 'A', 'B', 'C', 'Items processed'
+```
+
+### Promises
+
+`Promise.all()` provides another option for asynchronous loops over arrays. The main difference with the previous one is that `Promise.all()` executes all asynchronous operations in parallel. This means that promises will execute out of order, which might be an issue in some cases. Most often than not, this is my preferred solution as it's quite uncommon to want promises to execute sequentially.
+
+```js
+const asyncUppercase = item =>
+ new Promise(resolve =>
+ setTimeout(
+ () => resolve(item.toUpperCase()),
+ Math.floor(Math.random() * 1000)
+ )
+ );
+
+const uppercaseItems = () => {
+ const items = ['a', 'b', 'c'];
+ return Promise.all(
+ items.map(async item => {
+ const uppercaseItem = await asyncUppercase(item);
+ console.log(uppercaseItem);
+ })
+ ).then(() => {
+ console.log('Items processed');
+ });
+};
+// LOGS: 'A', 'C', 'B', 'Items processed'
+```
+
+### Array methods
+
+Unfortunately, array methods such as `Array.prototype.forEach()` do not work well with `async`/`await`. The only viable solution is to use `Promise.all()` as shown in the previous example. Using an `async` callback with `Array.prototype.forEach()` will result in the rest of the code executing and the asynchronous operations not being awaited for.
+
+```js
+const asyncUppercase = item =>
+ new Promise(resolve =>
+ setTimeout(
+ () => resolve(item.toUpperCase()),
+ Math.floor(Math.random() * 1000)
+ )
+ );
+
+const uppercaseItems = async () => {
+ const items = ['a', 'b', 'c'];
+ await items.forEach(async item => {
+ const uppercaseItem = await asyncUppercase(item);
+ console.log(uppercaseItem);
+ });
+
+ console.log('Items processed');
+};
+
+uppercaseItems();
+// LOGS: ''Items processed', 'B', 'A', 'C'
+```
diff --git a/articles/snippets/javascript-await-timeout.md b/articles/snippets/javascript-await-timeout.md
new file mode 100644
index 000000000..e11ddf04a
--- /dev/null
+++ b/articles/snippets/javascript-await-timeout.md
@@ -0,0 +1,106 @@
+---
+title: How can I add a timeout to a promise in JavaScript?
+shortTitle: Promise timeout
+type: question
+tags: [javascript,promise,timeout,class]
+author: chalarangelo
+cover: walking
+excerpt: Oftentimes you might need to add a timeout to a promise in JavaScript. Learn how to do this and more in this short guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Many times in the past I've found myself needing to add a timeout to a promise in JavaScript. `setTimeout()` is not exactly a perfect tool for the job, but it's easy enough to wrap it into a promise:
+
+```js
+const awaitTimeout = delay =>
+ new Promise(resolve => setTimeout(resolve, delay));
+
+awaitTimeout(300).then(() => console.log('Hi'));
+// Logs 'Hi' after 300ms
+
+const f = async () => {
+ await awaitTimeout(300);
+ console.log('Hi'); // Logs 'Hi' after 300ms
+};
+```
+
+There's nothing particularly complicated about this code sample, really. All it does is use the `Promise` constructor to wrap `setTimeout()` and resolve the promise after `delay` ms. This can be a useful tool when some code has to stall for a given amount of time.
+
+In order to add a timeout to another promise, however, there are two additional needs this utility has to satisfy. The first one is allowing the timeout promise to reject instead of resolving when provided a reason as a second argument. The other one is to create a wrapper function which will add the timeout to the promise:
+
+```js
+const awaitTimeout = (delay, reason) =>
+ new Promise((resolve, reject) =>
+ setTimeout(
+ () => (reason === undefined ? resolve() : reject(reason)),
+ delay
+ )
+ );
+
+const wrapPromise = (promise, delay, reason) =>
+ Promise.race([promise, awaitTimeout(delay, reason)]);
+
+wrapPromise(fetch('https://cool.api.io/data.json'), 3000, {
+ reason: 'Fetch timeout',
+})
+ .then(data => {
+ console.log(data.message);
+ })
+ .catch(data => console.log(`Failed with reason: ${data.reason}`));
+// Will either log the `message` if `fetch` completes in under 3000ms
+// or log an error message with the reason 'Fetch timeout' otherwise
+```
+
+As you can see in this example, `reason` is used to determine if the timeout promise will resolve or reject. `awaitTimeout()` is then used to create a new promise and passed to `Promise.race()` along with the other promise to create a timeout.
+
+This implementation definitely works, but we can take it a couple steps further. An obvious improvement is the addition of a way to clear a timeout, which requires storing the ids of any active timeouts. This, along with the need to make this utility self-contained both make a great case for using a `class`:
+
+```js
+class Timeout {
+ constructor() {
+ this.ids = [];
+ }
+
+ set = (delay, reason) =>
+ new Promise((resolve, reject) => {
+ const id = setTimeout(() => {
+ if (reason === undefined) resolve();
+ else reject(reason);
+ this.clear(id);
+ }, delay);
+ this.ids.push(id);
+ });
+
+ wrap = (promise, delay, reason) =>
+ Promise.race([promise, this.set(delay, reason)]);
+
+ clear = (...ids) => {
+ this.ids = this.ids.filter(id => {
+ if (ids.includes(id)) {
+ clearTimeout(id);
+ return false;
+ }
+ return true;
+ });
+ };
+}
+
+const myFunc = async () => {
+ const timeout = new Timeout();
+ const timeout2 = new Timeout();
+ timeout.set(6000).then(() => console.log('Hello'));
+ timeout2.set(4000).then(() => console.log('Hi'));
+ timeout
+ .wrap(fetch('https://cool.api.io/data.json'), 3000, {
+ reason: 'Fetch timeout',
+ })
+ .then(data => {
+ console.log(data.message);
+ })
+ .catch(data => console.log(`Failed with reason: ${data.reason}`))
+ .finally(() => timeout.clear(...timeout.ids));
+};
+// Will either log the `message` or log a 'Fetch timeout' error after 3000ms
+// The 6000ms timeout will be cleared before firing, so 'Hello' won't be logged
+// The 4000ms timeout will not be cleared, so 'Hi' will be logged
+```
diff --git a/articles/snippets/javascript-blank-value.md b/articles/snippets/javascript-blank-value.md
new file mode 100644
index 000000000..3abb913f6
--- /dev/null
+++ b/articles/snippets/javascript-blank-value.md
@@ -0,0 +1,97 @@
+---
+title: How can I check for a blank value in JavaScript?
+shortTitle: Value is blank
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: workspace-with-speaker
+excerpt: JavaScript doesn't have a built-in way to check if a value is blank, but it's easy to create one.
+dateModified: 2022-09-25T05:00:00-04:00
+---
+
+JavaScript doesn't have a built-in way to check if a value is blank, but it's easy to create one. Before we do, however, we should define the behavior of such a method. The inspiration for this comes from Rails' `blank?` method, but modified to fit JavaScript's needs.
+
+First of all, any falsy values should be considered blank. These include `null`, `undefined`, `0`, `false`, `''`, and `NaN`.
+
+```js
+const isFalsy = value => !value;
+
+isFalsy(null); // true
+isFalsy(undefined); // true
+isFalsy(0); // true
+isFalsy(false); // true
+isFalsy(''); // true
+isFalsy(NaN); // true
+```
+
+Secondly, empty arrays and objects should also be considered blank. This can be easily checked by using `Object.keys()` for both types of values.
+
+```js
+const isEmptyCollection = value =>
+ (Array.isArray(value) || value === Object(value)) &&
+ !Object.keys(value).length;
+
+isEmptyCollection([]); // true
+isEmptyCollection({}); // true
+```
+
+In addition to the empty string (`''`), whitespace-only strings should be considered blank, too. A regular expression can be used to check for this.
+
+```js
+const isWhitespaceString = value =>
+ typeof value === 'string' && /^\s*$/.test(value);
+
+isWhitespaceString(' '); // true
+isWhitespaceString('\t\n\r'); // true
+```
+
+Finally, we can check for some commonly-used built-in objects. Invalid `Date` instances, as well as empty `Set` and `Map` instances should all be considered blank.
+
+```js
+const isInvalidDate = value =>
+ value instanceof Date && Number.isNaN(value.getTime());
+const isEmptySet = value => value instanceof Set && value.size === 0;
+const isEmptyMap = value => value instanceof Map && value.size === 0;
+
+isInvalidDate(new Date('hello')); // true
+isEmptySet(new Set()); // true
+isEmptyMap(new Map()); // true
+```
+
+Putting everything together, we can finally set up our `isBlank` method.
+
+```js
+const isFalsy = value => !value;
+const isWhitespaceString = value =>
+ typeof value === 'string' && /^\s*$/.test(value);
+const isEmptyCollection = value =>
+ (Array.isArray(value) || value === Object(value)) &&
+ !Object.keys(value).length;
+const isInvalidDate = value =>
+ value instanceof Date && Number.isNaN(value.getTime());
+const isEmptySet = value => value instanceof Set && value.size === 0;
+const isEmptyMap = value => value instanceof Map && value.size === 0;
+
+const isBlank = value => {
+ if (isFalsy(value)) return true;
+ if (isWhitespaceString(value)) return true;
+ if (isEmptyCollection(value)) return true;
+ if (isInvalidDate(value)) return true;
+ if (isEmptySet(value)) return true;
+ if (isEmptyMap(value)) return true;
+ return false;
+};
+
+isBlank(null); // true
+isBlank(undefined); // true
+isBlank(0); // true
+isBlank(false); // true
+isBlank(''); // true
+isBlank(' \r\n '); // true
+isBlank(NaN); // true
+isBlank([]); // true
+isBlank({}); // true
+isBlank(new Date('hello')); // true
+isBlank(new Set()); // true
+isBlank(new Map()); // true
+```
diff --git a/articles/snippets/javascript-boolean-function.md b/articles/snippets/javascript-boolean-function.md
new file mode 100644
index 000000000..e8ab49a0d
--- /dev/null
+++ b/articles/snippets/javascript-boolean-function.md
@@ -0,0 +1,54 @@
+---
+title: Where and how can I use the Boolean function in JavaScript?
+shortTitle: Boolean function use-cases
+type: question
+tags: [javascript,function,type]
+author: chalarangelo
+cover: rocky-lake
+excerpt: JavaScript's Boolean function can be used for truth-checking data among other things. Learn how to use it and level up your code today.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript's built-in [`Boolean`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean) is one of those things I find myself suggesting in code reviews quite often as of late, so I thought I could share some tips about it with the world.
+
+### Using Boolean for truth-checking
+
+The `Boolean()` function is particularly useful when truth-checking data and probably significantly more readable than the double negation (`!!`) operation:
+
+```js
+let x = 'some-value';
+
+// This doesn't look too nice
+if (!!x) {
+ // ...
+}
+
+// This is a lot more readable
+if (Boolean(x)) {
+ // ...
+}
+```
+
+As you can see in the example above, it serves the exact same purpose and is pretty straightforward to use. Similarly, as `Boolean()` is itself a function returning a boolean value, you can use it for truth-checking collections, filtering arrays etc.:
+
+```js
+const values = [0, 0, 2, 0, 3];
+// Use as the callback for Array.prototype.some()
+const hasValidValue = values.some(Boolean);
+// Use as the callback for Array.prototype.filter()
+const nonEmptyValues = values.filter(Boolean);
+```
+
+### Handle Boolean objects with care
+
+While the `Boolean()` function is pretty useful, you might run into some issues with the `Boolean` object and the `Boolean` constructor. The `Boolean` object is an object wrapper for a boolean value, but the tricky part is that, as an object, it's always truthy even if the contained value is `false`!
+
+```js
+let x = new Boolean(false);
+
+if (x) {
+ // This code is executed
+}
+```
+
+For example, the above code will consider `x` truthy, even if it clearly contains `false` as its value. This might some confusing, but you can easily avoid it if you generally avoid using `Boolean` objects and the `Boolean` constructor, unless you are entirely certain that you need to use it for some reason. I cannot find any scenarios where I would need to use this, to be honest, so it might not be all that common to begin with.
diff --git a/articles/snippets/javascript-boolean-trap.md b/articles/snippets/javascript-boolean-trap.md
new file mode 100644
index 000000000..0bc955220
--- /dev/null
+++ b/articles/snippets/javascript-boolean-trap.md
@@ -0,0 +1,77 @@
+---
+title: Boolean traps and how to avoid them
+shortTitle: Boolean traps
+type: story
+tags: [javascript,function,type,boolean]
+author: chalarangelo
+cover: lighthouse
+excerpt: Boolean traps can cause readability and maintainability issues in your code. Learn what they are, how to spot and fix them in this article.
+dateModified: 2021-07-11T05:00:00-04:00
+---
+
+I recently came across the concept of **Boolean traps** and it instantly resonated with me due to the volume of Google searches I've performed because of it. In this article, I'll try to explain what it is, why it's somewhat of an anti-pattern, how to spot it in your code and ways to refactor around it.
+
+### Boolean trap - What's in a name?
+
+While the name **Boolean trap** might be unfamiliar to some, I'm pretty certain the concept it represents isn't. The simplest form of a boolean trap is a function that takes a boolean argument.
+
+The **trap** in the name might throw you off if you stick to this definition, but it serves its purpose. Let's look at two simple examples to get a better grasp of things:
+
+```js
+// What does `false` stand for?
+results.reload(false);
+
+// What does `true` stand for?
+const user = new User(true);
+```
+
+The first example suffers in terms of readability due to an obvious contradiction. A function named `reload` expects a boolean argument. `false` in this context must surely mean that no reloading should happen. Except that might not be the case. This argument might be anything from performing the operation immediately (i.e. `immediate`) to some side effect such as animation to even the no-op we suspected. I've stumbled upon similar cases of ambiguous arguments in many libraries in the past.
+
+The second example is also hard to decipher without looking at some documentation. Here, the constructor expects a boolean argument that might mean literally anything. Would you have guessed that it's a flag indicating if the user should have administrative privileges? Probably not. The point is there is no way to tell what this argument means without looking at the documentation.
+
+### Red flag or red herring?
+
+At this point, you might be asking yourself why this is actually bad. Reading through the documentation is expected. After all, that's what it's there for. Except this starts to become a waste of time on return visits. If you're working with a library and look up a boolean argument over and over because it's not obvious, it becomes a bit of a hassle.
+
+Moreover, code is read many times by many people. The author might be familiar with the library and API and have no need for documentation altogether. But the next person who comes along will have to visit the same documentation and figure it out for themselves. That harms readability and wastes tons of time in the long run, due to a single boolean argument.
+
+A bonus point here is the potential of further reducing readability by increasing cognitive load. There are valid use-cases for boolean arguments, but there are situations where the name of the function, being in itself a negative, with a negative (i.e. falsy) value makes the reader stop and pause to parse what's happening. For example:
+
+```js
+// Real quick: Is this valid or invalid?
+input.setInvalid(false);
+```
+
+### Not all booleans will trap you
+
+As with most things, there is no universal best practice here. Even though I often find boolean arguments hard to read, I understand there are cases where you might want to use them.
+
+```js
+// It should be obvious that `true` makes the element disabled
+element.setProperty('disabled', true);
+// Could be equivalent to `element.disabled = true;`
+```
+
+In this example, it's pretty straightforward what `true` does. Notice that the double negative from before might still make this slightly hard to read, but it makes sense to use a boolean in this context. Why? Well, it's essentially a setter function and passing the actual value of the property isn't such a bad idea.
+
+### Mitigating the problem
+
+We've already established what a boolean trap is and why it's bad. But how do we fix it? Even if we can spot the anti-pattern, it might be hard to change it before it affects a lot of code and developers. Some languages support named arguments and that usually solves the problem quite easily. JavaScript on the other hand doesn't, but there's always the option to pass an options object.
+
+Let's take a look at the two examples from before and how that would work:
+
+```js
+// Ok, so reload but not immediately
+results.reload({ immediate: false });
+
+// Create a new user without administrator privileges
+const user = new User({ isAdministrator: false });
+```
+
+Without huge changes to the API, we could have avoided the boolean trap altogether. All we needed was a plain JavaScript object. This also has the added benefit of making the function more extensible in the future. Objects are quite flexible, so if we want to add a second boolean (e.g. `animate` for `reload` or `active` for `User`), we need only add a key to the object.
+
+On a side note, while comments seem an appropriate solution, they will inevitably become stale and out of touch with the API. It's best to leave this kind of information to the official documentation or source code, instead.
+
+### Conclusion
+
+To summarize, boolean arguments in functions can be the source of a lot of wasted time and the cause for low code readability if used incorrectly. They're sometimes considered an anti-pattern as they increase cognitive load and reduce maintainability of shared code. Luckily, they're very easy to spot and fix using plain JavaScript option objects.
diff --git a/articles/snippets/javascript-callbacks.md b/articles/snippets/javascript-callbacks.md
new file mode 100644
index 000000000..0389c4ce0
--- /dev/null
+++ b/articles/snippets/javascript-callbacks.md
@@ -0,0 +1,59 @@
+---
+title: A cautionary tale about JavaScript callbacks
+shortTitle: Callback pitfalls
+type: story
+tags: [javascript,function]
+author: chalarangelo
+cover: rabbit-call
+excerpt: JavaScript callbacks are especially tricky when you're not careful. Take a deeper dive into potential issues and how to avoid them.
+dateModified: 2021-07-01T05:00:00-04:00
+---
+
+A piece of advice I've found myself repeating often as of late is this:
+
+> When working with callbacks in JavaScript, it's better to err on the side of caution and be more verbose.
+
+Mind you, I'm mostly repeating this to myself, but I thought it's pretty valuable to share it with the world. The reason is the myriads of issues I've stumbled upon due to seemingly harmless functions used as callbacks. And that's not even the worst part! They usually slip under the radar when you look at the code and might need a second or third look to identify as the culprit behind the issue.
+
+The most common bug I've encountered is one you might be familiar with: `parseInt()` used as a callback, especially in combination with `Array.prototype.map()`. Consider the following code:
+
+```js
+const nums = ['1', '5', '10', '21'];
+nums.map(parseInt); // [1, NaN, 2, 7]
+```
+
+Did you spot the problem? `parseInt()` takes up to two arguments: the `string` to be parsed and an optional `radix` parameter. `Array.prototype.map()` passes three parameters to the callback: the `value`, `index` and `array`. It should be obvious from this breakdown that the index of each element being passed as the radix parameter results in this strange problem.
+
+The solution is pretty straightforward, too. Creating a function to pass the arguments we want to `parseInt()` would fix this and remove a nasty bug somewhere down the line:
+
+```js
+const nums = ['1', '5', '10', '21'];
+nums.map(num => parseInt(num, 10)); // [1, 5, 10, 21]
+```
+
+A corollary to this is that when working with third-party libraries and APIs, it's always best to create a function to pass the data to whatever part of said API is being used rather than using it directly as a callback. The reason for this is that, even though the library or API might not expect any additional arguments now, this might change in a later version. Not accounting for this could be a major risk when updating to a new version of a library marked as having no breaking changes. Take a look at the following example:
+
+```js
+// third-party-lib@v1.0.0
+const parseData = path => {
+ const fileData = fs.readFileSync(path);
+ return fileData || '';
+};
+
+const importantFiles = ['id-card.txt', 'bank-number.txt'];
+importantFiles.map(parseData); // Works fine
+
+// third-party-lib@v1.1.0 - No breaking changes!
+const parseData = (path, purge) => {
+ const fileData = fs.readFileSync(path);
+ if (purge) fs.unlinkSync(path);
+ return fileData || '';
+};
+
+const importantFiles = ['id-card.txt', 'bank-number.txt'];
+importantFiles.map(parseData); // 'bank-number.txt'` has been deleted
+```
+
+The example above, while a bit unlikely, demonstrates a case where a simple index from `Array.prototype.map()` could wreak havoc on the entire filesystem due to a harmless version bump of an external dependency. This is the kind of bug that is hard to track down and causes a ton of headaches when debugging as you struggle to understand how a version bump without breaking changes could cause this.
+
+To summarize, be extra careful when working with callbacks. If a function is not explicitly designed to be a callback, if you are using third party code, even if you are uncertain just add a function to pass down the arguments. It will save you time in the long run at the cost of your code looking a tiny bit more verbose. I think it's a worthwhile tradeoff.
diff --git a/articles/snippets/javascript-classical-vs-prototypal-inheritance.md b/articles/snippets/javascript-classical-vs-prototypal-inheritance.md
new file mode 100644
index 000000000..bf00cf471
--- /dev/null
+++ b/articles/snippets/javascript-classical-vs-prototypal-inheritance.md
@@ -0,0 +1,65 @@
+---
+title: How does JavaScript's prototypal inheritance differ from classical inheritance?
+shortTitle: Prototypal vs classical inheritance
+type: question
+tags: [javascript,object,class]
+author: chalarangelo
+cover: last-light
+excerpt: Understanding the difference between these two object-oriented programming paradigms is key to taking your skills to the next level.
+dateModified: 2021-11-21T05:00:00-04:00
+---
+
+### Object-oriented programming
+
+Both classical and prototypal inheritance are **object-oriented programming paradigms**. Objects in object-oriented programming are abstractions that encapsulate the properties of an entity. This is known as abstraction.
+
+When dealing with multiple levels of abstraction, each level is more general or more specific. The more general abstraction of a more specific abstraction is called a generalization.
+
+As mentioned previously, objects are abstraction of entities. We use either classes (classical inheritance) or prototypes (prototypal inheritance) to create generalizations of these objects. Generalizations are created by inheritance.
+
+Consider an example:
+
+- We have two objects representing two pets: Max the dog and Claire the cat. Let's call them `max` and `claire` respectively.
+- All dogs have common characteristics. Therefore we can create an abstraction, `Dog`, which encapsulates their common characteristics. We can use inheritance to pass characteristics from `Dog` to `max`.
+- The same applies for cats, allowing us to create an abstraction, `Cat`. Similarly, `claire` will inherit characteristics from `Cat`.
+- Cats and dogs share some common characteristics. We can create a generalization, `Animal`, to encapsulate those characteristics. `Dog` and `Cat` inherit these common characteristics from `Animal`.
+
+### Classical inheritance
+
+In classical object-oriented programming, there are two types of abstractions: objects and classes. An object is an abstractions of an entity, while a class is either an abstraction of an object or another class.
+
+If we were to model the previous example using classical inheritance, it would look something like this:
+
+```js
+class Animal { }
+
+class Dog extends Animal { }
+class Cat extends Animal { }
+
+const max = new Dog();
+max.name = 'Max';
+
+const claire = new Cat();
+claire.name = 'Claire';
+```
+
+### Prototypal inheritance
+
+In prototypal object-oriented programming, there's only one type of abstraction: objects. Objects are either abstractions of entities or other objects, in which case they're called prototypes. Hence a prototype is a generalization.
+
+Objects can be created out of nothing or from another object, which in turn becomes the prototype of the newly created object.
+
+If we were to model the previous example using prototypal inheritance, it would look something like this:
+
+```js
+const animal = {};
+
+const dog = Object.create(animal);
+const cat = Object.create(animal);
+
+const max = Object.create(dog);
+max.name = 'Max';
+
+const claire = Object.create(cat);
+claire.name = 'Claire';
+```
diff --git a/articles/snippets/javascript-closures.md b/articles/snippets/javascript-closures.md
new file mode 100644
index 000000000..8fc458488
--- /dev/null
+++ b/articles/snippets/javascript-closures.md
@@ -0,0 +1,54 @@
+---
+title: What are JavaScript closures?
+shortTitle: Closures introduction
+type: question
+tags: [javascript,function,closure]
+author: chalarangelo
+cover: cherry-trees
+excerpt: Learn and understand closures, a core concept in JavaScript programming, and level up your code.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Closures are a JavaScript concept that comes up quite a lot, especially during interviews. While they sound confusing, they are not all that complicated and you have probably already used them in your code regardless of your expertise level. Let's start with what a closure is:
+
+> You have a closure when a function accesses variables defined outside of it.
+
+That doesn't sound too complicated. Let's see an example:
+
+```js
+const items = [
+ { id: 1, title: 'First' },
+ { id: 2, title: 'Second' },
+ { id: 3, title: 'Final' }
+];
+const matcher = /^F/;
+const filteringFn = x => matcher.test(x.title);
+items.filter(filteringFn); // [{ id: 1, title: 'First' }, { id: 3, title: 'Final' }]
+```
+
+The above example defines some data to play around with, a regular expression to use for matching and a function, `filteringFn` that is then used in `Array.prototype.filter()` as the filtering function. If you look closely at `filteringFn`, you'll notice it uses a variable defined outside of, namely `matcher`. This is a closure.
+
+Let's look at another, more complex example:
+
+```js
+const initCounter = (start = 0) => {
+ let value = start;
+ return {
+ get: () => value,
+ increment: () => ++value,
+ decrement: () => --value,
+ reset: () => value = start
+ };
+}
+
+const counter = initCounter(5);
+counter.get(); // 5
+counter.increment(); // 6
+counter.increment(); // 7
+counter.decrement(); // 6
+counter.reset(); // 5
+```
+
+In this example, we define a function, `initCounter`, that returns an object, whose properties are functions. All of the returned object's properties use closures to manipulate `initCounter`'s `value` variable in some way. The obvious benefit of this approach is that if you want to define multiple counters via `initCounter`, you do not need to create multiple `value` instances all over the place, but they are safely encapsulated by the returned object, using closures.
+
+Using closures, as shown in the example above, can help make your code more usable and maintainable, while allowing you to separate concerns and create abstractions as necessary.
diff --git a/articles/snippets/javascript-copy-array.md b/articles/snippets/javascript-copy-array.md
new file mode 100644
index 000000000..c6dcf3195
--- /dev/null
+++ b/articles/snippets/javascript-copy-array.md
@@ -0,0 +1,66 @@
+---
+title: How can I clone an array in JavaScript?
+shortTitle: Clone an array
+type: question
+tags: [javascript,array]
+author: chalarangelo
+cover: colorful-plastic
+excerpt: Pick up a few new tricks which you can use to clone arrays in JavaScript.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript provides quite a few ways to clone an array, most of which are pretty similar in terms of performance and results. Here's a quick rundown of some of the available options.
+
+#### The spread operator
+
+ES6 introduced the spread operator (`...`), which provides probably the easiest and most common way to create a shallow clone of an array.
+
+```js
+let x = [1, 2, 3, 4];
+let y = [...x];
+```
+
+#### Array.from()
+
+`Array.from()` has a very powerful API that can be used for many different things, including creating a copy of an array.
+
+```js
+let x = [1, 2, 3, 4];
+let y = Array.from(x);
+```
+
+#### Array.prototype.slice()
+
+Similarly to the spread operator, `Array.prototype.slice()` can be used to create a shallow copy of an array.
+
+```js
+let x = [1, 2, 3, 4];
+let y = x.slice();
+```
+
+#### Array.prototype.map()
+
+Looking into one of the more unorthodox options, `Array.prototype.map()` can be used to map each element of an array to itself to create a new array.
+
+```js
+let x = [1, 2, 3, 4];
+let y = x.map(i => i);
+```
+
+#### Array.prototype.filter()
+
+Similarly, `Array.prototype.filter()` can be used to return `true` for each and every element, resulting in a new array with all of the original array's elements.
+
+```js
+let x = [1, 2, 3, 4];
+let y = x.filter(() => true);
+```
+
+#### Object.assign()
+
+Finally, `Object.assign()` can be used in the exact same way as it's used to create a clone of an object, but for an array instead.
+
+```js
+let x = [1, 2, 3, 4];
+let y = Object.assign([], x);
+```
diff --git a/articles/snippets/javascript-date-comparison.md b/articles/snippets/javascript-date-comparison.md
new file mode 100644
index 000000000..1e2e55dc9
--- /dev/null
+++ b/articles/snippets/javascript-date-comparison.md
@@ -0,0 +1,42 @@
+---
+title: How do I compare two dates in JavaScript?
+shortTitle: Date comparison
+type: question
+tags: [javascript,date,comparison]
+author: chalarangelo
+cover: pineapple-at-work
+excerpt: Learn how you can compare two dates in JavaScript using various different techniques.
+dateModified: 2022-01-16T05:00:00-04:00
+---
+
+### Equality comparison
+
+Comparing two dates in JavaScript using the loose or strict equality operators (`==` or `===`) is not recommended for most cases. Equality operators compare the `Date` object references, resulting in `false`, even if the date values are the same:
+
+```js
+const a = new Date(2022, 01, 10);
+const b = new Date(2022, 01, 10);
+
+a === b; // false
+```
+
+### Date.prototype.getTime()
+
+One way to compare two `Date` values is using the `Date.prototype.getTime()` method. This method returns a number indicating the number of milliseconds elapsed since the Unix Epoch:
+
+```js
+const a = new Date(2022, 01, 10);
+const b = new Date(2022, 01, 10);
+
+a.getTime() === b.getTime(); // true
+```
+
+### Other methods
+
+As mentioned before, `Date.prototype.getTime()` is one way to compare two `Date` values. It's not the only one way to compare them. Other options are the following:
+
+- `Date.prototype.toISOString()`
+- `Date.prototype.toUTCString()`
+- `Date.prototype.toLocaleDateString()` provided you use the same locale
+
+All of these methods produce consistent results, but we still recommend `Date.prototype.getTime()` due to its simplicity.
diff --git a/articles/snippets/javascript-deep-freeze-object.md b/articles/snippets/javascript-deep-freeze-object.md
new file mode 100644
index 000000000..efab9365c
--- /dev/null
+++ b/articles/snippets/javascript-deep-freeze-object.md
@@ -0,0 +1,80 @@
+---
+title: How can I deep freeze an object in JavaScript?
+shortTitle: Deep freeze object
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: frozen-globe
+excerpt: Learn how mutability works in JavaScript, its applications to objects and how you can properly freeze them to make them constant.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Objects in JavaScript are mutable, regardless if you define them as `const` variables or not. In fact, using `const` when defining an object only prevents the variable from being reassigned. However, you can reassign the properties of a `const` object or array, like this:
+
+```js
+const myObj = { a: 10, b: 20, c: 30 };
+myObj.a = 12; // { a: 12, b: 20, c: 30 };
+
+const myArr = [15, 25, 35];
+myArr[1] = 28; // [15, 28, 35];
+```
+
+To make an object immutable, we can utilize `Object.freeze()`, which will prevent the addition of new properties and prevent deletion and changes to existing properties to some extent. However, while `Object.freeze()` provides somewhat of a solution, it only mitigates the problem to the next nesting level, as in reality it performs a shallow freeze. This means that properties that are objects or arrays can still be mutated:
+
+```js
+const myObj = {
+ a: 1,
+ b: 'hello',
+ c: [0, 1, 2],
+ d: { e: 1, f: 2 }
+};
+Object.freeze(myObj);
+
+myObj.a = 10;
+myObj.b = 'hi';
+myObj.c[1] = 4;
+myObj.d.e = 0;
+/*
+myObj = {
+ a: 1,
+ b: 'hello',
+ c: [0, 4, 2],
+ d: { e: 0, f: 2 }
+}
+*/
+```
+
+As you can see, `Object.freeze()` is a step in the right direction, but only shallow freezes the object. To solve the issue we can use recursion, checking if each property is itself an object and, if `Object.isFrozen()` is `false`, apply `Object.freeze()` to it:
+
+```js
+const myObj = {
+ a: 1,
+ b: 'hello',
+ c: [0, 1, 2],
+ d: { e: 1, f: 2 }
+};
+
+const deepFreeze = obj => {
+ Object.keys(obj).forEach(prop => {
+ if (typeof obj[prop] === 'object' && !Object.isFrozen(obj[prop])) deepFreeze(obj[prop]);
+ });
+ return Object.freeze(obj);
+};
+deepFreeze(myObj);
+
+myObj.a = 10;
+myObj.b = 'hi';
+myObj.c[1] = 4;
+myObj.d.e = 0;
+
+/*
+myObj = {
+ a: 1,
+ b: 'hello',
+ c: [0, 1, 2],
+ d: { e: 1, f: 2 }
+}
+*/
+```
+
+In the above example, we apply the techniques we described previously to ensure that the given object is deeply frozen. You can view the complete code, along with more examples in the [deepFreeze](/js/s/deep-freeze) snippet.
diff --git a/articles/snippets/javascript-destructuring-assignment.md b/articles/snippets/javascript-destructuring-assignment.md
new file mode 100644
index 000000000..72a1ceb88
--- /dev/null
+++ b/articles/snippets/javascript-destructuring-assignment.md
@@ -0,0 +1,70 @@
+---
+title: Where and how can I use the destructuring assignment syntax in JavaScript?
+shortTitle: Destructuring assignment introduction
+type: question
+tags: [javascript,array,object]
+author: chalarangelo
+cover: building-blocks
+excerpt: Learn the basics of the destructuring assignment syntax in JavaScript ES6 and improve your code with this easy guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+The destructuring assignment syntax, first introduced in JavaScript ES6, allows the **unpacking of values** from arrays and objects into distinct variables. While it might seem intimidating at first, it's actually quite easy to learn and use. Let's break it down into easier to understand cases.
+
+### Array destructuring
+
+Destructuring an array is very straightforward. All you have to do is declare a variable for each value in the sequence. You can define fewer variables than there are indexes in the array (i.e. if you only want to unpack the first few values), skip some indexes or even use the rest pattern to unpack any remaining values into a new array.
+
+```js
+const nums = [ 3, 6, 9, 12, 15 ];
+const [
+ k, // k = 3
+ l, // l = 6
+ , // Skip a value (9)
+ ...n // n = [12, 15]
+] = nums;
+```
+
+### Object destructuring
+
+Object destructuring is pretty similar to array destructuring, the main difference being that you can reference each key in the object by name, creating a variable with the same name. Additionally, you can also unpack a key to a new variable name, unpack only the keys you need and use the rest pattern to unpack remaining keys into a new object.
+
+```js
+const obj = { a: 1, b: 2, c: 3, d: 4 };
+const {
+ a, // a = 1
+ c: d, // d = 3
+ ...rest // rest = { b: 2, d: 4 }
+} = obj;
+```
+
+### Nested destructuring
+
+Nested objects and arrays can be unpacked by following the same rules. The difference here is that you can unpack nested keys or values directly to variables without having to store the parent object in a variable itself.
+
+```js
+const nested = { a: { b: 1, c: 2 }, d: [1, 2]};
+const {
+ a: {
+ b: f, // f = 1
+ ...g // g = { c: 2 }
+ },
+ ...h // h = { d: [1, 2]}
+} = nested;
+```
+
+### Advanced destructuring
+
+As arrays act much like objects, it's possible to use the destructuring assignment syntax to get specific values from an array by using the index as a key in an object destructuring assignment. Additionally, using this method, you can get other properties of the array (e.g. its `length`). Finally, you can also define default values for variables in a destructuring assignment, in case the unpacked value is `undefined`.
+
+```js
+const arr = [ 5, 'b', 4, 'd', 'e', 'f', 2 ];
+const {
+ 6: x, // x = 2
+ 0: y, // y = 5
+ 2: z, // z = 4
+ length: count, // count = 7
+ name = 'array', // name = 'array' (not present in arr)
+ ...restData // restData = { '1': 'b', '3': 'd', '4': 'e', '5': 'f' }
+} = arr;
+```
diff --git a/articles/snippets/javascript-empty-array.md b/articles/snippets/javascript-empty-array.md
new file mode 100644
index 000000000..67f2e54f0
--- /dev/null
+++ b/articles/snippets/javascript-empty-array.md
@@ -0,0 +1,48 @@
+---
+title: How do I empty an array in JavaScript?
+shortTitle: Empty an array
+type: question
+tags: [javascript,array]
+author: chalarangelo
+cover: coconuts
+excerpt: You can use a lot of different techniques to empty an array in JavaScript. See which ones best suits your needs with this quick guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+When working with JavaScript arrays, a pretty common question is how does one empty an array and remove all its elements. As it turns out, there are a few ways you can go about this, each one with its pros and cons.
+
+### Assign it to an empty array
+
+You can assign your variable to an empty array (`[]`) in order to clear it. While this option is rather fast, you should be mindful of references to the original array, as they will remain unchanged. Moreover, it doesn't work for arrays declared as `const`.
+
+```js
+let a = [1, 2, 3, 4];
+a = [];
+```
+
+### Set its length to 0
+
+A better option is to set the `length` of the array to `0`. This option is also pretty fast and has the additional benefit of working for `const` variables.
+
+```js
+let a = [1, 2, 3, 4];
+a.length = 0;
+```
+
+### Use Array.prototype.splice()
+
+`Array.prototype.splice()` can also be a useful alternative when trying to empty an array. While it has no other downsides compared to the previous method, it doesn't seem to perform as well, so that might be something to consider.
+
+```js
+let a = [1, 2, 3, 4];
+a.splice(0, a.length);
+```
+
+### Use Array.prototype.pop()
+
+Last but not least, using `Array.prototype.pop()` is another, more old-fashioned option. It's generally more verbose and less performant, so I'd rather use one of the previous methods instead.
+
+```js
+let a = [1, 2, 3, 4];
+while (a.length) a.pop();
+```
diff --git a/articles/snippets/javascript-encodeuri-encodeuricomponent.md b/articles/snippets/javascript-encodeuri-encodeuricomponent.md
new file mode 100644
index 000000000..49b76c1c8
--- /dev/null
+++ b/articles/snippets/javascript-encodeuri-encodeuricomponent.md
@@ -0,0 +1,40 @@
+---
+title: What is the difference between encodeURI() and encodeURIComponent() in JavaScript?
+shortTitle: encodeURI() vs encodeURIComponent()
+type: question
+tags: [javascript,browser]
+author: chalarangelo
+cover: laptop-view
+excerpt: JavaScript provides two methods for encoding characters to URL-safe strings. Do you know when to use each one?
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### encodeURIComponent()
+
+The [`encodeURIComponent()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent) function encodes everything in the given string, except `A-Z a-z 0-9 - _ . ! ~ * ' ( )`. You should use this function if the string you are encoding is only part of a URL.
+
+```js
+const partOfURL = 'my-page#with,speci@l&/"characters"?';
+const fullURL = 'https://my-website.com/my-page?query="a%b"&user=1';
+
+encodeURIComponent(partOfURL); // Good, escapes special characters
+// 'my-page%23with%2Cspeci%40l%26%2F%22characters%22%3F'
+
+encodeURIComponent(fullURL); // Bad, encoded URL is not valid
+// 'https%3A%2F%2Fmy-website.com%2Fmy-page%3Fquery%3D%22a%25b%22%26user%3D1'
+```
+
+### encodeURI()
+
+The [`encodeURI()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI) function encodes everything in the given string, except `A-Z a-z 0-9 ; , / ? : @ & = + $ - _ . ! ~ * ' ( ) #`. You should use this function if the string you are encoding is a full URL.
+
+```js
+const partOfURL = 'my-page#with,speci@l&/"characters"?';
+const fullURL = 'https://my-website.com/my-page?query="a%b"&user=1';
+
+encodeURI(partOfURL); // Bad, does not escape all special characters
+// 'my-page#with,speci@l&/%22characters%22?'
+
+encodeURI(fullURL); // Good, encoded URL is valid
+// 'https://my-website.com/my-page?query=%22this%25thing%22&user=1'
+```
diff --git a/articles/snippets/javascript-enum.md b/articles/snippets/javascript-enum.md
new file mode 100644
index 000000000..d138c6156
--- /dev/null
+++ b/articles/snippets/javascript-enum.md
@@ -0,0 +1,59 @@
+---
+title: How can I define an enum in JavaScript?
+shortTitle: Enum implementation
+type: question
+tags: [javascript,object,class,symbol,generator]
+author: chalarangelo
+cover: book-chair
+excerpt: Enums are part of TypeScript, but what about defining enums in plain old JavaScript? Here are a few way you can do that.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+TypeScript's enums are a very convenient feature present in many other languages. JavaScript, however, does not have a similar concept at this time. But what JavaScript lacks in syntactic sugar it makes up for in terms of flexibility.
+
+The easiest way to define an enum would be to use `Object.freeze()` in combination with a plain object. This will ensure that the enum object cannot be mutated.
+
+```js
+const daysEnum = Object.freeze({
+ monday: 0,
+ tuesday: 1,
+ wednesday: 2,
+ thursday: 3,
+ friday: 4,
+ saturday: 5,
+ sunday: 6
+});
+```
+
+Taking this one step further, one could extract the logic into a function with a variable number of arguments and producing a frozen object. There is very little benefit to this technique, so a better alternative would be to create a simple `class`. After all, enums are more common in object-oriented programming languages, so this sounds like a great fit.
+
+An `Enum` class would only require a `constructor` with a variable number of arguments. Its job is to add each key to the enum object and freeze the newly created instance. A potential enhancement would be to provide access to the enum values as strings. Obviously, this can be accomplished using `Object.keys()`, but a named method could result in a conflict with one of the enum's values, let alone the method polluting the result.
+
+Using an ES6 symbol is the obvious solution here, as it will not pollute the result of `Object.keys()` and it will never conflict with any values in the enum. Taking this one step further, `Symbol.iterator` would be a great choice as it would allow for the enum to be considered iterable and make it even more useful. Putting all of this together, here's my `Enum` class and how to use it:
+
+```js
+class Enum {
+ constructor(...keys) {
+ keys.forEach((key, i) => {
+ this[key] = i;
+ });
+ Object.freeze(this);
+ }
+
+ *[Symbol.iterator]() {
+ for (let key of Object.keys(this)) yield key;
+ }
+}
+
+const daysEnum = new Enum(
+ 'monday',
+ 'tuesday',
+ 'wednesday',
+ 'thursday',
+ 'friday',
+ 'saturday',
+ 'sunday'
+);
+
+const days = [...daysEnum]; // Array of the enum values as strings
+```
diff --git a/articles/snippets/javascript-equality.md b/articles/snippets/javascript-equality.md
new file mode 100644
index 000000000..de3544b38
--- /dev/null
+++ b/articles/snippets/javascript-equality.md
@@ -0,0 +1,54 @@
+---
+title: What is the difference between JavaScript's equality operators?
+shortTitle: JavaScript equality operators
+type: question
+tags: [javascript,type,comparison]
+author: chalarangelo
+cover: beach-pineapple
+excerpt: Learn all you need to know about the differences between JavaScript's double equals and triple equals operators.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript provides two equality operators used for comparisons:
+
+- The double equals (`==`), also known as the loose equality operator
+- The triple equals (`===`), also known as the strict equality operator
+
+The key difference between the two is that the triple equals (`===`) operator compares both type and value, whereas the double equals (`==`) operator uses type coercion so that both operands are of the same type, then compares only the resulting values.
+
+Here are some examples to clear up any confusion:
+
+```js
+const num = 0;
+const str = '0';
+const obj = new String(0);
+const bool = false;
+const undef = undefined;
+const nil = null;
+
+console.dir([
+ num == str, // 0 == 0, true
+ num == bool, // 0 == 0, true
+ str == obj, // '0' == '0', true
+ obj == num, // 0 == 0, true
+ bool == str, // 0 == 0, true
+ bool == obj, // 0 == 0, true
+ bool == nil, // false
+ undef == nil, // true
+ undef == bool, // false
+]);
+
+console.dir([
+ num === str, // types don't match, false
+ num === bool, // types don't match, false
+ str === obj, // types don't match, false
+ obj === num, // types don't match, false
+ bool === str, // types don't match, false
+ bool === obj, // types don't match, false
+ bool === nil, // types don't match, false
+ undef === nil, // types don't match, false
+ undef === bool, // types don't match, false
+]);
+```
+
+As you can see from the examples above, using the triple equals (`===`) operator is far more predictable and intuitive than the double equals (`==`) operator. Therefore, we recommend you use the triple equals (`===`) operator for most cases, unless you are entirely certain you want type coercion to be applied to the comparison's operands.
diff --git a/articles/snippets/javascript-event-bubbling-capturing-delegation.md b/articles/snippets/javascript-event-bubbling-capturing-delegation.md
new file mode 100644
index 000000000..148cceae3
--- /dev/null
+++ b/articles/snippets/javascript-event-bubbling-capturing-delegation.md
@@ -0,0 +1,88 @@
+---
+title: Understanding event bubbling, capturing and delegation in JavaScript
+shortTitle: Event bubbling, capturing and delegation
+type: story
+tags: [javascript,browser,event]
+author: chalarangelo
+cover: fishermen
+excerpt: Understand how events work in JavaScript and learn when to use event bubbling, event capturing and event delegation with this short guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Event bubbling
+
+Bubbling means that the event propagates from the target element (i.e. the `button` the user clicked) up through its ancestor tree, starting from the nearest one. By default, all events bubble.
+
+To better understand event bubbling, consider the following HTML example, which we will be referring to for most of this article:
+
+```html
+
+
+
+ Click me
+
+
+
+```
+
+```js
+const ancestors = [
+ window, document, document.documentElement,
+ document.body, document.getElementById('btn-container')
+];
+
+// Target phase
+document.querySelector('.btn').addEventListener('click', e => {
+ console.log(`Hello from ${e.target}`);
+});
+// Bubble phase
+ancestors.forEach(a => {
+ a.addEventListener('click', e => {
+ console.log(`Hello from ${e.currentTarget}`);
+ });
+});
+```
+
+If we add an event listener to each element in the tree, as shown above, we would see a listener fired by the `button` first, then each one of the others firing from the nearest ancestor all the way up to `Window`.
+
+### Event capturing
+
+Capturing is the exact opposite of bubbling, meaning that the outer event handlers are fired before the most specific handler (i.e. the one on the `button`). Note that all capturing event handlers are run first, then all the bubbling event handlers.
+
+You can use event capturing by applying a third argument to [`EventTarget.addEventListener`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener), setting it to `true`. For example:
+
+```js
+// Capture phase
+ancestors.forEach(a => {
+ a.addEventListener('click', e => {
+ console.log(`Hello from ${e.currentTarget}`);
+ }, true);
+});
+```
+
+Given this code, we would see a listener fired for each ancestor of the `button` first and then the listener of the `button` would fire.
+
+### Event propagation
+
+Having explained event bubbling and capturing, we can now explain the three phases of event propagation:
+
+- During the **capture phase**, the event starts from `Window` and moves down to `Document`, the root element and through ancestors of the target element.
+- During the **target phase**, the event gets triggered on the event target (e.g. the `button` the user clicked).
+- During the **bubble phase**, the event bubbles up through ancestors of the target element until the root element, `Document` and, finally, `Window`.
+
+### Event delegation
+
+Event delegation refers to the idea of delegating event listening to parent elements instead of adding event listeners directly to the event targets. Using this technique, the parent can catch and handle the bubbling events as necessary.
+
+```js
+window.addEventListener('click', e => {
+ if (e.target.className === 'btn') console.log('Hello there!');
+});
+```
+
+In the above example, we delegate event handling from the `button` to `Window` and use `Event.target` to get the original event's target.
+
+Using the event delegation pattern is advantageous for two reasons:
+
+- By using event delegation, we can listen for events on a large amount of elements without having to attach event listeners individually, which can provide performance benefits.
+- By using event delegation, dynamic elements (i.e. added or removed from the DOM over the course of time) can have their events captured and handled without requiring listeners to be registered or removed.
diff --git a/articles/snippets/javascript-event-loop-explained.md b/articles/snippets/javascript-event-loop-explained.md
new file mode 100644
index 000000000..965249ce0
--- /dev/null
+++ b/articles/snippets/javascript-event-loop-explained.md
@@ -0,0 +1,116 @@
+---
+title: What is the Event Loop in JavaScript?
+shortTitle: Event loop explained
+type: question
+tags: [javascript,browser,event]
+author: chalarangelo
+cover: tranquility
+excerpt: The Event Loop is a source of confusion for many developers, but it's a fundamental piece of the JavaScript engine.
+dateModified: 2022-08-21T05:00:00-04:00
+---
+
+The Event Loop is a source of confusion for many developers, but it's a fundamental piece of the JavaScript engine. It's what allows JavaScript to be single-threaded, yet able to execute in a non-blocking fashion. To understand the Event Loop, we first need to explain a few things about the JavaScript engine, such as the Call Stack, Tasks, Microtasks and their respective Queues. Let's break them down one by one.
+
+### The Call Stack
+
+The **Call Stack** is a data structure that keeps track of the execution of JavaScript code. As the name suggests, it's a stack, thus a LIFO (Last In, First Out) data structure in memory. Each function that's executed is represented as a frame in the Call Stack and placed on top of the previous function.
+
+Let's look at a simple example, step by step:
+
+```js
+function foo() {
+ console.log('foo');
+ bar();
+}
+
+function bar() {
+ console.log('bar');
+}
+```
+
+1. The Call Stack is initially empty.
+2. The function `foo()` is pushed onto the Call Stack.
+3. The function `foo()` is executed and popped off the Call Stack.
+4. The function `console.log('foo')` is pushed onto the Call Stack.
+5. The function `console.log('foo')` is executed and popped off the Call Stack.
+6. The function `bar()` is pushed onto the Call Stack.
+7. The function `bar()` is executed and popped off the Call Stack.
+8. The function `console.log('bar')` is pushed onto the Call Stack.
+9. The function `console.log('bar')` is executed and popped off the Call Stack.
+10. The Call Stack is now empty.
+
+### Tasks and the Task Queue
+
+**Tasks** are scheduled, synchronous blocks of code. While executing, they have exclusive access to the Call Stack and can also enqueue other tasks. Between Tasks, the browser can perform rendering updates. Tasks are stored in the **Task Queue**, waiting to be executed by their associated functions. The Task Queue, in turn, is a FIFO (First In, First Out) data structure. Examples of Tasks include the callback function of an event listener associated with an event and the callback of `setTimeout()`.
+
+### Microtasks an the Microtask Queue
+
+**Microtasks** are similar to Tasks in that they're scheduled, synchronous blocks of code with exclusive access to the Call Stack while executing. Additionally, they are stored in their own FIFO (First In, First Out) data structure, the **Microtask Queue**. Microtasks differ from Tasks, however, in that the Microtask Queue must be emptied out after a Task completes and before re-rendering. Examples of Microtasks include `Promise` callbacks and `MutationObserver` callbacks.
+
+Microtasks and the Microtask Queue are also referred to as Jobs and the Job Queue.
+
+### The Event Loop
+
+Finally, the **Event Loop** is a loop that keeps running and checks if the Call Stack is empty. It processes Tasks and Microtasks, by placing them in the Call Stack one at a time and also controls the rendering process. It's made up of four key steps:
+
+1. **Script evaluation:** Synchronously executes the script until the Call Stack is empty.
+2. **Task processing:** Select the first Task in the Task Queue and run it until the Call Stack is empty.
+3. **Microtask processing:** Select the first Microtask in the Microtask Queue and run it until the Call Stack is empty, repeating until the Microtask Queue is empty.
+4. **Rendering:** Re-render the UI and loop back to step 2.
+
+### A practical example
+
+To better understand the Event Loop, let's look at a practical example, incorporating all of the above concepts:
+
+```js
+console.log('Script start');
+
+setTimeout(() => console.log('setTimeout()'), 0);
+
+Promise.resolve()
+ .then(() => console.log('Promise.then() #1'))
+ .then(() => console.log('Promise.then() #2'));
+
+console.log('Script end');
+
+// LOGS:
+// Script start
+// Script end
+// Promise.then() #1
+// Promise.then() #2
+// setTimeout()
+```
+
+Does the output look like what you expected? Let's break down what's happening, step by step:
+
+1. The Call Stack is initially empty. The Event Loop begins evaluating the script.
+2. `console.log()` is pushed to the Call Stack and executed, logging `'Script start'`.
+3. `setTimeout()` is pushed to the Call Stack and executed. This creates a new Task for its callback function in the Task Queue.
+4. `Promise.prototype.resolve()` is pushed to the Call Stack and executed, calling in turn `Promise.prototype.then()`.
+5. `Promise.prototype.then()` is pushed to the Call Stack and executed. This creates a new Microtask for its callback function in the Microtask Queue.
+6. `console.log()` is pushed to the Call Stack and executed, logging `'Script end'`.
+7. The Event Loops has finished its current Task, evaluating the script. It then begins running the first Microtask in the Microtask Queue, which is the callback of `Promise.prototype.then()` that was queued in step 5.
+8. `console.log()` is pushed to the Call Stack and executed, logging `'Promise.then() #1'`.
+9. `Promise.prototype.then()` is pushed to the Call Stack and executed. This creates a new entry for its callback function in the Microtask Queue.
+10. The Event Loop checks the Microtask Queue. As it’s not empty, it executes the first Microtask, which is the callback of `Promise.prototype.then()` that was queued in step 10.
+11. `console.log()` is pushed to the Call Stack and executed, logging `'Promise.then() #2'`.
+12. Re-rendering would occur here, if there was any.
+13. The Microtask Queue is empty, so the Event Loop moves to the Task Queue and executes the first Task, which is the callback of `setTimeout()` that was queued in step 3.
+14. `console.log()` is pushed to the Call Stack and executed, logging `'setTimeout()'`.
+15. Re-rendering would occur here, if there was any.
+16. The Call Stack is now empty.
+
+### Summary
+
+- The **Event Loop** is responsible for executing the JavaScript code. It first evaluates and executes the script, then processes **Tasks** and **Microtasks**.
+- **Tasks** and **Microtasks** are scheduled, synchronous blocks of code. They are executed one at a time, and are placed in the **Task Queue** and **Microtask Queue**, respectively.
+- For all of these, the **Call Stack** is used to keep track of function calls.
+- Whenever **Microtasks** are executed, the **Microtask Queue** must be emptied out before the next **Task** can be executed.
+- **Rendering** occurs between **Tasks**, but not between **Microtasks**.
+
+### Notes
+
+- The script evaluation step of the Event Loop is in itself treated similarly to a Task.
+- The second argument of `setTimeout()` indicates a minimum time until execution, not a guaranteed time. This is due to the fact that Tasks execute in order and that Microtasks may be executed in-between.
+- The behavior of the event loop in Node.js is similar, but has some differences. Most notably, there is no rendering step.
+- Older browser versions did not completely respect the order of operations, so Tasks and Microtasks may execute in different orders.
diff --git a/articles/snippets/javascript-evil-closures.md b/articles/snippets/javascript-evil-closures.md
new file mode 100644
index 000000000..405bfc100
--- /dev/null
+++ b/articles/snippets/javascript-evil-closures.md
@@ -0,0 +1,68 @@
+---
+title: Are JavaScript closures inherently evil?
+shortTitle: Closures and hidden state
+type: story
+tags: [javascript,function,closure]
+author: chalarangelo
+cover: silver-flat-screen
+excerpt: Closures are used frequently, yet often misunderstood. Understanding them in depth is crucial to be able to write clean, maintainable code.
+dateModified: 2022-05-18T05:00:00-04:00
+---
+
+JavaScript closures are used frequently, yet often misunderstood. Understanding them in depth is crucial to be able to write clean, maintainable and bug-free code. We previously discussed what they are and how they work.
+
+I strongly recommend you read the [previous article on closures](/articles/s/javascript-closures) if you haven't already. Instead of rehashing the same information, I would like to discuss the dangers of using closures and present my view on the topic.
+
+### Hidden state
+
+The main argument against closures is that of hidden state. Hidden state refers to obscuring the state of an object or, in this case, a function. The argument is that **internal mutable state** can create unpredictable behavior and unexpected results. Due to this, it's often said that hidden state is the root of all evil when it comes to programming.
+
+While the argument in itself has some merit, I don't much like the generalization. There are perfectly valid cases where hidden state is expected, even practically a necessity. However, it's true that hidden state can create bugs and unmaintainable code.
+
+An example of hidden state due to closures would be the one presented in my original introduction to the topic:
+
+```js
+const initCounter = (start = 0) => {
+ let value = start;
+ return {
+ get: () => value,
+ increment: () => ++value,
+ decrement: () => --value,
+ reset: () => value = start
+ };
+}
+
+const counter = initCounter(5);
+counter.get(); // 5
+counter.increment(); // 6
+counter.increment(); // 7
+counter.decrement(); // 6
+counter.reset(); // 5
+```
+
+In this scenario, the `initCounter` function returns an object that contains hidden mutable state in the form of the `value` variable. Obviously, this is a very simple example, but `counter.get()` or `counter.increment()` in isolation would be considered non-deterministic expressions. There is no way to know the result of a method call like that without analyzing the surrounding code.
+
+While this is not uncommon, it can get more complicated when shared state comes into play or many pieces of code are interacting with one another. The common remedy to this issue is to use **functional programming** and refactor the hidden mutable state into an argument or a shared global variable.
+
+### Access to context
+
+Not all closures are created equal. In fact, there are perfectly valid use-cases of closures that can make life a lot easier. For example, **accessing shared constants** should be considered pretty safe. After all, if you want truly pure functions you shouldn't even access globals and web APIs. This would be pretty impractical, as you would have to pass each global and API as an argument to the function.
+
+Although reasonably safe, it's important to ensure that constants are initialized before being used and explicitly throw an error, if not. Additionally, adequate documentation of such closures will minimize friction and make sure other developers understand what's going on. Finally, providing an escape hatch, usually in the form of **default arguments** that can be overridden, should be considered if possible.
+
+Here's an example of a simple random number generator, following these rules:
+
+```js
+const randomNumber = (limit = 100, random = Math.random) => random() * limit;
+
+randomNumber(10); // 4.0
+randomNumber(10, () => 0.2); // 2.0
+```
+
+Another benefit of these practices is that writing tests is a lot easier, as there's no confusion as to what needs to be mocked at any given time. In this example, we can easily replace `Math.random()` with any function that we want and know the resulting value.
+
+### Conclusion
+
+Closures in themselves are just another language feature that you have to wrap your head around. As a rule of thumb, use them sparingly, clarify your code's intent and provide escape hatches to reduce potential error surface.
+
+When used correctly, they can be another tool in your arsenal. Yet, if you use them poorly, they can create some really nasty bugs or unmaintainable code. It takes time to get used to them and be able to spot anti-patterns before they become a problem.
diff --git a/articles/snippets/javascript-expression-statement.md b/articles/snippets/javascript-expression-statement.md
new file mode 100644
index 000000000..c318a888f
--- /dev/null
+++ b/articles/snippets/javascript-expression-statement.md
@@ -0,0 +1,26 @@
+---
+title: What is the difference between an expression and a statement in JavaScript?
+shortTitle: Expressions and statements
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: forest-balcony
+excerpt: JavaScript distinguishes expressions and statements. Learn their differences in this short article.
+dateModified: 2021-11-07T05:00:00-04:00
+---
+
+JavaScript distinguishes expressions and statements. An **expression** is any valid unit of code that resolves to a value. A **statement** is a unit of code that performs an action. Some examples:
+
+```js
+// Statements
+let x = 0;
+function add(a, b) { return a + b; }
+if (true) { console.log('Hi'); }
+
+// Expressions
+x; // Resolves to 0
+3 + x; // Resolves to 3
+add(1, 2); // Resolves to 3
+```
+
+Anywhere JavaScript expects a statement, you can also write an expression. This kind of statement is called an **expression statement**. Conversely, you cannot write a statement where JavaScript expects an expression.
diff --git a/articles/snippets/javascript-for-in-for-of-foreach.md b/articles/snippets/javascript-for-in-for-of-foreach.md
new file mode 100644
index 000000000..f422228e0
--- /dev/null
+++ b/articles/snippets/javascript-for-in-for-of-foreach.md
@@ -0,0 +1,54 @@
+---
+title: What is the difference between JavaScript's for...in, for...of and forEach?
+shortTitle: JavaScript iteration methods comparison
+type: question
+tags: [javascript,array,object,iterator]
+author: chalarangelo
+cover: lake-loop
+excerpt: Learn the differences between the three most commonly used iteration methods in JavaScript, that often confuse beginners and veterans alike.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+`for...in` is used to iterate over all enumerable properties of an object, including inherited enumerable properties. This iteration statement can be used with arrays strings or plain objects, but not with `Map` or `Set` objects.
+
+```js
+for (let prop in ['a', 'b', 'c'])
+ console.log(prop); // 0, 1, 2 (array indexes)
+
+for (let prop in 'str')
+ console.log(prop); // 0, 1, 2 (string indexes)
+
+for (let prop in {a: 1, b: 2, c: 3})
+ console.log(prop); // a, b, c (object property names)
+
+for (let prop in new Set(['a', 'b', 'a', 'd']))
+ console.log(prop); // undefined (no enumerable properties)
+```
+
+`for...of` is used to iterate over iterable objects, iterating over their values instead of their properties. This iteration statement can be used with arrays, strings, `Map` or `Set` objects, but not with plain objects.
+
+```js
+for (let val of ['a', 'b', 'c'])
+ console.log(val); // a, b, c (array values)
+
+for (let val of 'str')
+ console.log(val); // s, t, r (string characters)
+
+for (let val of {a: 1, b: 2, c: 3})
+ console.log(prop); // TypeError (not iterable)
+
+for (let val of new Set(['a', 'b', 'a', 'd']))
+ console.log(val); // a, b, d (Set values)
+```
+
+Finally, `forEach()` is a method of the `Array` prototype, which allows you to iterate over the elements of an array. While `forEach()` only iterates over arrays, it can access both the value and the index of each element while iterating.
+
+```js
+['a', 'b', 'c'].forEach(
+ val => console.log(val) // a, b, c (array values)
+);
+
+['a', 'b', 'c'].forEach(
+ (val, i) => console.log(i) // 0, 1, 2 (array indexes)
+);
+```
diff --git a/articles/snippets/javascript-for-loop-early-break.md b/articles/snippets/javascript-for-loop-early-break.md
new file mode 100644
index 000000000..0fc474df2
--- /dev/null
+++ b/articles/snippets/javascript-for-loop-early-break.md
@@ -0,0 +1,46 @@
+---
+title: "Tip: Use JavaScript for loops if you need to break out early"
+shortTitle: For loops for early breaking
+type: tip
+tags: [javascript,array,loop]
+author: chalarangelo
+cover: armchair
+excerpt: Iteration in JavaScript can be done a handfuld of ways, most often using array methods, but sometimes a `for` loop is the best option.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+The usefulness of the humble `for` loop in modern JavaScript is rarely talked about. Apart from it being particularly useful in [asynchronous operation scenarios](/blog/s/javascript-async-array-loops), it can also make your code a lot more performant shall you need to break out of a loop early. Consider the following example:
+
+```js
+const smallArray = [0, 2];
+const largeArray = Array.from({ length: 1000 }, (_, i) => i);
+
+const areEqual = (a, b) => {
+ let result = true;
+ a.forEach((x, i) => {
+ if (!result) return;
+ if (b[i] === undefined || x !== b[i]) result = false;
+ });
+ return result;
+}
+
+areEqual(largeArray, smallArray); // false
+// Will loop over all items in `largeArray`
+```
+
+Obviously, the code isn't optimized, but it highlights the issue of array methods, such as `Array.prototype.forEach()` being unable to break out of the loop early. To counteract this, we could use a `for` loop and an early `return` instead:
+
+```js
+const smallArray = [0, 2];
+const largeArray = Array.from({ length: 1000 }, (_, i) => i);
+
+const areEqual = (a, b) => {
+ for (let i in a) {
+ if (b[i] === undefined || a[i] !== b[i]) return false;
+ }
+ return true;
+}
+
+areEqual(largeArray, smallArray); // false
+// Will only loop until the first mismatch is encountered
+```
diff --git a/articles/snippets/javascript-function-call-apply-bind.md b/articles/snippets/javascript-function-call-apply-bind.md
new file mode 100644
index 000000000..381422e77
--- /dev/null
+++ b/articles/snippets/javascript-function-call-apply-bind.md
@@ -0,0 +1,65 @@
+---
+title: JavaScript function methods - call(), apply() and bind()
+shortTitle: Function methods - call(), apply() and bind()
+type: story
+tags: [javascript,function]
+author: chalarangelo
+cover: canoe
+excerpt: Learn everything you need to know about JavaScript's `call()`, `apply()` and `bind()` in this short guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Function.prototype.call()
+
+`Function.prototype.call()` is used to call a function with a given `this` context and any arguments provided individually. For example:
+
+```js
+function printThisAndData(...data) {
+ console.log(this.data, ...data);
+}
+
+const obj = { data: 0 };
+const data = [1, 2, 3];
+
+printThisAndData.call(obj, data); // logs: 0 [1, 2, 3]
+printThisAndData.call(obj, ...data); // logs: 0 1 2 3
+```
+
+### Function.prototype.apply()
+
+`Function.prototype.apply()` is almost identical to `Function.prototype.call()` in the sense that it calls a function with a given `this` context, however it requires arguments to be provided as an array. For example:
+
+```js
+function printThisAndData(...data) {
+ console.log(this.data, ...data);
+}
+
+const obj = { data: 0 };
+const data = [1, 2, 3];
+
+printThisAndData.apply(obj, data); // logs: 0 1 2 3
+printThisAndData.apply(obj, ...data); // Throws a TypeError
+```
+
+### Function.prototype.bind()
+
+`Function.prototype.bind()` is slightly different from the previous two methods. Instead of calling a function with the given `this` context and returning the result, it returns a function with its `this` context bound and any arguments provided individually prepended to the arguments at the time of calling the returned function. For example:
+
+```js
+function printThisAndData(...data) {
+ console.log(this.data, ...data);
+}
+
+const obj = { data: 0 };
+const data = [1, 2, 3];
+
+const printObjAndData = printThisAndData.bind(obj);
+
+printObjAndData(data); // logs: 0 [1, 2, 3]
+printObjAndData(...data); // logs: 0 1 2 3
+
+const printObjTwoAndData = printThisAndData.bind(obj, 2);
+
+printObjTwoAndData(data); // logs: 0 2 [1, 2, 3]
+printObjTwoAndData(...data); // logs: 0 2 1 2 3
+```
diff --git a/articles/snippets/javascript-higher-order-functions.md b/articles/snippets/javascript-higher-order-functions.md
new file mode 100644
index 000000000..92c4cf6da
--- /dev/null
+++ b/articles/snippets/javascript-higher-order-functions.md
@@ -0,0 +1,30 @@
+---
+title: Understanding higher-order functions in JavaScript
+shortTitle: Higher-order functions
+type: story
+tags: [javascript,function]
+author: chalarangelo
+cover: rock-climbing
+excerpt: Learn everything you need to know about higher-order functions with this short guide and level up your programming skills.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+Higher-order functions are **functions that operate on other functions**, either by accepting them as arguments or by returning them as their results. This allows us to create an abstraction layer over actions, not just values.
+
+The reason we can write higher-order functions in JavaScript is due to the fact that functions are values. This means they can be assigned to variables and passed as values. You might also often hear the term _callback_ when referring to a function that is passed as an argument. This is due to it being called by the higher-order function. Callbacks are particularly common in JavaScript, with event handling, asynchronous code and array operations relying heavily on them.
+
+The main advantages of this technique are abstraction, composition, code reusability and readability. Most of the 30 seconds of code snippets are built with higher-order functions in mind. They are small, easily digestible functions that are **highly reusable** and **can be composed** to create more complex logic.
+
+That being said, we can take a look at an example, utilizing some very simple functions:
+
+```js
+const add = (a, b) => a + b;
+const isEven = num => num % 2 === 0;
+
+const data = [2, 3, 1, 5, 4, 6];
+
+const evenValues = data.filter(isEven); // [2, 4, 6]
+const evenSum = data.filter(isEven).reduce(add); // 12
+```
+
+In this example, we define two simple functions that we then use as callbacks in `Array.prototype.reduce()` and `Array.prototype.filter()` to get the result we want. Both of these functions are higher-order functions. This allows us to create an **abstraction layer for any action** we might want to perform without having to rewrite how the filtering or reduction algorithm is to be applied every single time.
diff --git a/articles/snippets/javascript-iife.md b/articles/snippets/javascript-iife.md
new file mode 100644
index 000000000..041ae8a1d
--- /dev/null
+++ b/articles/snippets/javascript-iife.md
@@ -0,0 +1,46 @@
+---
+title: What is an IIFE in JavaScript?
+shortTitle: IIFE introduction
+type: question
+tags: [javascript,function]
+author: chalarangelo
+cover: tropical-waterfall
+excerpt: An Immediately Invoked Function Expression (IIFE) is a JavaScript trick that trips up many developers. Here's what you need to know.
+dateModified: 2021-06-14T12:00:00+03:00
+---
+
+An **Immediately Invoked Function Expression** (IIFE for short) is a JavaScript function that is immediately invoked as soon as it's evaluated by the JavaScript runtime. Here's what it looks like alongside a roughly equivalent piece of code:
+
+```js
+// IIFE
+(function (message) {
+ console.log(message);
+})('Hello World');
+// LOGS: 'Hello World'
+
+// Equivalent code using named function
+function logMessage(message) {
+ console.log(message);
+}
+
+logMessage('Hello World'); // LOGS: 'Hello World'
+```
+
+Remember the "roughly equivalent" part? The only difference is the use of a named function instead of an anonymous one. From this example, it should be easy to deduce the anatomy of an IIFE, breaking it down into its parts:
+
+- Optional leading semicolon to avoid `TypeError`s in cases of minification etc.
+- An anonymous function, containing all the code that we want to invoke.
+- Opening and closing parentheses to wrap the anonymous function.
+- Parentheses to call the function and any arguments to invoke it with.
+
+Note that you can also use arrow functions for IIFEs, if you like. Just make sure to remember the differences between regular and arrow functions in that case. Our previous articles on [arrow functions](/blog/s/javascript-arrow-functions) and [the `this` keyword](/blog/s/javascript-this) should just about cover them.
+
+```js
+// All of these are equivalent, leading semicolon is optional
+;(() => console.log('Hello'))();
+;(function(){ console.log('Hello'); })();
+;(function(){ console.log('Hello'); })();
+;(function(){ console.log('Hello'); }());
+```
+
+IIFEs are often used to run some code, while keeping it and its variables out of the global scope. They are often criticized for lack of readability and how they are confusing to beginners. Additionally, they started going out of fashion with the rise of JavaScript modules and transpilers, so they might be less and less common as time goes by.
diff --git a/articles/snippets/javascript-index-for-of-loop.md b/articles/snippets/javascript-index-for-of-loop.md
new file mode 100644
index 000000000..c1689f2e7
--- /dev/null
+++ b/articles/snippets/javascript-index-for-of-loop.md
@@ -0,0 +1,25 @@
+---
+title: "Tip: Get the index of an array item in a JavaScript for...of loop"
+shortTitle: Array index in for...of loops
+type: tip
+tags: [javascript,array,iterator]
+author: chalarangelo
+cover: cave-view
+excerpt: Did you know you can get the index of an array item in a JavaScript for...of loop? Learn how with this bite-sized tip.
+dateModified: 2021-07-25T05:00:00-04:00
+---
+
+JavaScript's `for...of` loops provide an easy way to iterate over all kinds of iterables from arrays and stings to `Map` and `Set` objects. One supposed limitation over other options (e.g. `Array.prototype.forEach()`) is that you only get the value of each item in the iterable. But that is not necessarily the case, as you can easily leverage `Array.prototype.entries()` to get both the index and value of each array item:
+
+```js
+const items = ['a', 'b', 'c'];
+
+for (let [index, item] of items.entries()) {
+ console.log(`${index}: ${item}`);
+}
+// LOGS: 0: a, 1: b, 2: c
+```
+
+Moreover, you can use the spread operator (`...`) to convert a string into an array and then use `Array.prototype.entries()` the same way. Finally, both `Map` and `Set` prototypes provide a similar method (`Map.prototype.entries()` and `Set.prototype.entries()` respectively), which can be used the exact same way.
+
+_If you're not familiar with `for...of` and its syntax, I highly recommending you take a look at [this article about the various iteration methods in JavaScript](/articles/s/javascript-for-in-for-of-foreach)._
diff --git a/articles/snippets/javascript-iterable-to-array.md b/articles/snippets/javascript-iterable-to-array.md
new file mode 100644
index 000000000..0ef951d15
--- /dev/null
+++ b/articles/snippets/javascript-iterable-to-array.md
@@ -0,0 +1,46 @@
+---
+title: How do I convert an iterable to an array in JavaScript?
+shortTitle: Iterable to array
+type: question
+tags: [javascript,object,array,string]
+author: chalarangelo
+cover: waves
+excerpt: Learn how to use the JavaScript ES6 spread syntax to converting iterables to arrays and level up your code today.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript ES6 introduced, among many other things, the [spread operator (`...`)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax), which allows an iterable to be expanded in places where zero or more arguments or elements are expected.
+
+We can use the spread operator to convert iterables or, as they are sometimes referred to, array-likes. Let's take a look at some examples:
+
+### String
+
+When the spread operator is applied to a string, the result is an array of strings each one representing a character of the original string:
+
+```js
+const name = 'Zelda';
+const letters = [...name]; // 'Z', 'e', 'l', 'd', 'a'
+```
+
+### Set
+
+A [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) is a collection of unique values. When the spread operator is applied to it, the result is an array of the stored values:
+
+```js
+const data = [1, 2, 3, 1, 2, 4]
+const values = new Set(data);
+const uniqueValues = [...values]; // [1, 2, 3, 4]
+```
+
+Note that the above example is the basis for the [uniqueElements snippet](/js/s/unique-elements).
+
+### NodeList
+
+A [NodeList](https://developer.mozilla.org/en-US/docs/Web/API/NodeList) is a collection of nodes, returned by methods such as `Document.childNodes()` or `Document.querySelectorAll()`. While it implements some methods that help manipulate it as an array (e.g. `NodeList.prototype.forEach()`), it's oftentimes desirable to convert it to an array. When the spread operator is applied to it, the result is an array of the contained nodes:
+
+```js
+const nodes = document.childNodes;
+const nodeArray = [...nodes]; // [ , html ]
+```
+
+Note that the above example is the basis for the [nodeListToArray snippet](js/s/node-list-to-array).
diff --git a/articles/snippets/javascript-iterators.md b/articles/snippets/javascript-iterators.md
new file mode 100644
index 000000000..e2d376f40
--- /dev/null
+++ b/articles/snippets/javascript-iterators.md
@@ -0,0 +1,95 @@
+---
+title: What are JavaScript Iterators and where can I use them?
+shortTitle: JavaScript iterators introduction
+type: question
+tags: [javascript,array,object,iterator]
+author: chalarangelo
+cover: balloons
+excerpt: Learn how JavaScript's iterators work and how you can use them to level up your projects by understanding these short code examples.
+dateModified: 2021-09-26T13:20:57+03:00
+---
+
+JavaScript iterators were introduced in ES6 and they are used to loop over a sequence of values, usually some sort of collection. By definition, an iterator must implement a `next()` function, that returns an object in the form of `{ value, done }` where `value` is the next value in the iteration sequence and `done` is a boolean determining if the sequence has already been consumed.
+
+A very simple iterator with practical use in a real-world project could be as follows:
+
+```js
+class LinkedList {
+ constructor(data) {
+ this.data = data;
+ }
+
+ firstItem() {
+ return this.data.find(i => i.head);
+ }
+
+ findById(id) {
+ return this.data.find(i => i.id === id);
+ }
+
+ [Symbol.iterator]() {
+ let item = { next: this.firstItem().id };
+ return {
+ next: () => {
+ item = this.findById(item.next);
+ if (item) {
+ return { value: item.value, done: false };
+ }
+ return { value: undefined, done: true };
+ },
+ };
+ }
+}
+
+const myList = new LinkedList([
+ { id: 'a10', value: 'First', next: 'a13', head: true },
+ { id: 'a11', value: 'Last', next: null, head: false },
+ { id: 'a12', value: 'Third', next: 'a11', head: false },
+ { id: 'a13', value: 'Second', next: 'a12', head: false },
+]);
+
+for (let item of myList) {
+ console.log(item); // 'First', 'Second', 'Third', 'Last'
+}
+```
+
+In the above example, we implement a [`LinkedList` data structure](/articles/s/js-data-structures-linked-list), that internally uses a `data` array. Each item in it has a `value` and some implementation-specific properties used to determine its position in the sequence. Objects constructed from this class are not iterable by default. To define an iterator we use `Symbol.iterator` and set it up so that the returned sequence is in order based on the internal implementation of the class, while the returned items only return their `value`.
+
+On a related note, iterators are just functions, meaning they can be called like any other function (e.g. to delegate the iteration to an existing iterator), while also not being restricted to the `Symbol.iterator` name. This allows us to define multiple iterators for the same object. Here's an example of these concepts at play:
+
+```js
+class SpecialList {
+ constructor(data) {
+ this.data = data;
+ }
+
+ [Symbol.iterator]() {
+ return this.data[Symbol.iterator]();
+ }
+
+ values() {
+ return this.data
+ .filter(i => i.complete)
+ .map(i => i.value)
+ [Symbol.iterator]();
+ }
+}
+
+const myList = new SpecialList([
+ { complete: true, value: 'Lorem ipsum' },
+ { complete: true, value: 'dolor sit amet' },
+ { complete: false },
+ { complete: true, value: 'adipiscing elit' },
+]);
+
+for (let item of myList) {
+ console.log(item); // The exact data passed to the SpecialList constructor above
+}
+
+for (let item of myList.values()) {
+ console.log(item); // 'Lorem ipsum', 'dolor sit amet', 'adipiscing elit'
+}
+```
+
+In this example, we use the native array iterator of the `data` object to make our `SpecialList` iterable, returning the exact values of the `data` array. Meanwhile, we also define a `values` method, which is an iterator itself, using `Array.prototype.filter()` and `Array.prototype.map()` on the `data` array. Finally, we return the `Symbol.iterator` of the result, allowing iteration only over non-empty objects in the sequence and returning just the `value` for each one.
+
diff --git a/articles/snippets/javascript-json-stringify-pick-keys.md b/articles/snippets/javascript-json-stringify-pick-keys.md
new file mode 100644
index 000000000..7baf239b6
--- /dev/null
+++ b/articles/snippets/javascript-json-stringify-pick-keys.md
@@ -0,0 +1,57 @@
+---
+title: "Tip: Serialize specific properties from a JSON object"
+shortTitle: Selective property serialization
+type: tip
+tags: [javascript,object,json]
+author: chalarangelo
+cover: coffee-drip
+excerpt: Have you ever wanted to serialize an object but only include certain keys? Turns out JavaScript provides an easy way to do this!
+dateModified: 2021-07-06T05:00:00-04:00
+---
+
+The default behavior for `JSON.stringify()` is to pull all serializable properties from the given object. However, there are many scenarios where you might want to pick a specific subset of keys from an object. This problem is handled by the second argument of `JSON.stringify()` by passing it either an array of keys or a replacer function.
+
+### Array of keys
+
+An array of keys allows you to pick specific keys to be included in the stringified version of the object. This is particularly useful when you know the exact shape of the serialized object you want.
+
+```js
+const user = {
+ id: 1234,
+ username: 'johnsmith',
+ name: 'John Smith',
+ age: 39
+};
+
+JSON.stringify(user, ['username', 'name']);
+// '{ "username": "johnsmith", "name": "John Smith" }'
+```
+
+### Replacer function
+
+A replacer function is more versatile than an array of keys and takes both the key and value as its arguments. Apart from using it to include or exclude keys, it can also be useful in altering the value of each key in the stringified representation of the object. In order for a key to be included in the output, the replacer function must return a serializable value (string, number, boolean, null or object).
+
+```js
+class Point {
+ constructor (x, y) {
+ this.x = x;
+ this. y = y;
+ }
+}
+
+const target = {
+ id: 1234,
+ location: new Point(10, 20),
+ name: 'Delivery point',
+};
+
+JSON.stringify(target, (key, value) => {
+ // Exclude id
+ if (key === 'id') return undefined;
+ // Convert location to an array of coordinates
+ if (value instanceof Point) return [value.x, value.y];
+ // Return other properties (i.e. name) without modification
+ return value;
+});
+// '{ "location": [10, 20], "name": "Delivery point" }'
+```
diff --git a/articles/snippets/javascript-listen-once.md b/articles/snippets/javascript-listen-once.md
new file mode 100644
index 000000000..f747ea555
--- /dev/null
+++ b/articles/snippets/javascript-listen-once.md
@@ -0,0 +1,61 @@
+---
+title: How can I execute an event handler at most once?
+shortTitle: Execute event handler only once
+type: question
+tags: [javascript,browser,event]
+cover: dog-waiting
+excerpt: Learn how to attach an event handler to events that is executed at most once in this JavaScript article.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### jQuery
+
+Back in the day when jQuery was all the rage, we would usually use [`$.one()`](https://api.jquery.com/one/) to create an event handler that would execute at most once for a given event per element. A simple example would be as follows:
+
+```html
+Click me!
+```
+
+```js
+$('#my-btn').one('click', () => {
+ console.log('Hello!'); // 'Hello!' will only be logged on the first click
+});
+```
+
+### Using a flag
+
+However, jQuery seems to have fallen out of favor lately and thus many developers have resorted to writing their version of `$.one()`. An implementation could look like this:
+
+```js
+const listenOnce = (el, evt, fn) => {
+ let fired = false;
+ el.addEventListener(evt, (e) => {
+ if (!fired) fn(e);
+ fired = true;
+ });
+};
+
+listenOnce(
+ document.getElementById('my-btn'),
+ 'click',
+ () => console.log('Hello!')
+); // 'Hello!' will only be logged on the first click
+```
+
+In this implementation, we use a flag, `fired`, to check if the event has been triggered before and only execute the passed callback, `fn`, the first time the event is triggered. There are some details that we might have omitted such as removing the listener, but overall this is a reasonably solid implementation.
+
+### Event listener options
+
+If you are targeting modern browsers (i.e. not IE), [`EventTarget.addEventListener()`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) has introduced the `options` object parameter, which allows us to pass a few different flags, one of which is `once`. Setting `once` to `true` results in the exact same behavior as the snippet above with minimal effort.
+
+Here's one way to write the previous snippet using `once`, which also happens to be how we implemented the latest version of the [listenOnce snippet](/js/s/listen-once):
+
+```js
+const listenOnce = (el, evt, fn) => el.addEventListener(evt, fn, { once: true });
+
+listenOnce(
+ document.getElementById('my-btn'),
+ 'click',
+ () => console.log('Hello!')
+); // 'Hello!' will only be logged on the first click
+```
diff --git a/articles/snippets/javascript-make-iterable.md b/articles/snippets/javascript-make-iterable.md
new file mode 100644
index 000000000..8346a86c5
--- /dev/null
+++ b/articles/snippets/javascript-make-iterable.md
@@ -0,0 +1,33 @@
+---
+title: "Tip: Make any JavaScript value iterable"
+shortTitle: Make any value iterable
+type: tip
+tags: [javascript,array,iterator,generator]
+author: chalarangelo
+cover: colorful-plastic
+excerpt: Did you know you can define an iterator for any JavaScript value? This quick tip will show you how.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript's `Symbol.iterator` is a very powerful tool that every web developer should learn how to use. It allows you to define and customize the way a value is iterated, effectively allowing you to make any value iterable. You can easily apply this knowledge to plain JavaScript objects and even classes.
+
+All you need to correctly define an iterator is a generator function `yield`ing each of the iteration values. This could be used to retrieve key-value pairs in an object, call specific getter functions from a class or split a number into an array of digits:
+
+```js
+const obj = { a: 1, b: 2, c: 3 };
+
+obj[Symbol.iterator] = function* () {
+ for (let key of Object.keys(obj)) yield { [key]: obj[key] };
+};
+
+[...obj]; // [ { a: 1 }, { b: 2 }, { c: 3 }]
+
+class IterableNumber extends Number {
+ *[Symbol.iterator]() {
+ for (let digit of [...`${this}`].map(d => Number.parseInt(d))) yield digit;
+ }
+}
+
+const num = new IterableNumber(1337);
+[...num]; // [ 1, 3, 3, 7]
+```
diff --git a/articles/snippets/javascript-memoization.md b/articles/snippets/javascript-memoization.md
new file mode 100644
index 000000000..0fb0f6d9e
--- /dev/null
+++ b/articles/snippets/javascript-memoization.md
@@ -0,0 +1,68 @@
+---
+title: Where and how can I use memoization in JavaScript?
+shortTitle: Memoization introduction
+type: question
+tags: [javascript,function,memoization]
+author: chalarangelo
+cover: cherry-trees
+excerpt: Learn different ways to memoize function calls in JavaScript as well as when to use memoization to get the best performance results.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+Memoization is a commonly used technique that can help speed up your code significantly. This technique relies on a **cache** to store results for previously completed units of work. The purpose of the cache is to **avoid performing the same work more than once**, speeding up subsequent calls of time-consuming functions. Based on this definition, we can easily extract some criteria that can help us decide when to use memoization in our code:
+
+- Memoization is useful mainly in speeding up slow-performing, costly or time-consuming function calls
+- Memoization speeds up subsequent calls, so it's best used when you anticipate multiple calls of the same function under the same circumstances
+- Memoization stores results in memory, so it should be avoided when the same function is called multiple times under very different circumstances
+
+A simple, object-oriented example of implementing memoization could be as follows:
+
+```js
+class MyObject {
+ constructor(data) {
+ this.data = data;
+ this.data[this.data.length - 2] = { value: 'Non-empty' };
+ }
+
+ firstNonEmptyItem() {
+ return this.data.find(v => !!v.value);
+ }
+
+ firstNonEmptyItemMemo() {
+ if (!this.firstNonEmpty)
+ this.firstNonEmpty = this.data.find(v => !!v.value);
+ return this.firstNonEmpty;
+ }
+}
+
+const myObject = new MyObject(Array(2000).fill({ value: null }));
+
+for (let i = 0; i < 100; i ++)
+ myObject.firstNonEmptyItem(); // ~4000ms
+for (let i = 0; i < 100; i ++)
+ myObject.firstNonEmptyItemMemo(); // ~70ms
+```
+
+This example showcases a way to implement memoization inside a class. However, it makes a couple of assumptions. First, it's assumed that the `data` structure will not be altered over the lifecycle of the object. Seconds, it's assumed that this is the only expensive function call we will make, so the code is not reusable. The example also doesn't account for arguments being passed to the function, which would alter the result. A functional approach would work with any given function and also account for arguments. Such an approach can be seen in the form of the [memoize snippet](/js/s/memoize/), which uses a `Map` to store different values.
+
+We still recommend using that snippet as the primary way to memoize a function, however JavaScript's [Proxy object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) provides an interesting alternative via the use of the `handler.apply()` trap, which can be used for this purpose as follows:
+
+```js
+const memoize = fn => new Proxy(fn, {
+ cache: new Map(),
+ apply (target, thisArg, argsList) {
+ let cacheKey = argsList.toString();
+ if(!this.cache.has(cacheKey))
+ this.cache.set(cacheKey, target.apply(thisArg, argsList));
+ return this.cache.get(cacheKey);
+ }
+});
+
+const fibonacci = n => (n <= 1 ? 1 : fibonacci(n - 1) + fibonacci(n - 2));
+const memoizedFibonacci = memoize(fibonacci);
+
+for (let i = 0; i < 100; i ++)
+ fibonacci(30); // ~5000ms
+for (let i = 0; i < 100; i ++)
+ memoizedFibonacci(30); // ~50ms
+```
diff --git a/articles/snippets/javascript-merge-arrays.md b/articles/snippets/javascript-merge-arrays.md
new file mode 100644
index 000000000..f56bc92c3
--- /dev/null
+++ b/articles/snippets/javascript-merge-arrays.md
@@ -0,0 +1,57 @@
+---
+title: How do I merge two arrays in JavaScript?
+shortTitle: Merge arrays
+type: question
+tags: [javascript,array]
+author: chalarangelo
+cover: arrays
+excerpt: Arrays are one of the most used data types in any programming language. Learn how to merge two arrays in JavaScript with this short guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Spread operator
+
+The [spread operator (`...`)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) was introduced in ES6 and can be used to merge two or more arrays, by spreading each one inside a new array:
+
+```js
+const a = [1, 2, 3];
+const b = [4, 5, 6];
+
+const merged = [...a, ...b]; // [1, 2, 3, 4, 5, 6]
+```
+
+### Array.prototype.concat()
+
+[`Array.prototype.concat()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/concat) is a method on the `Array` prototype and can be used to create a new array, either by concatenating both arrays to a new array or one array to the other. Both methods result in a new array, without mutating the original:
+
+```js
+const a = [1, 2, 3];
+const b = [4, 5, 6];
+
+const merged = [].concat(a, b); // [1, 2, 3, 4, 5, 6]
+// -- OR --
+const alsoMerged = a.concat(b); // [1, 2, 3, 4, 5, 6]
+```
+
+### Comparing the two
+
+The spread operator version is definitely shorter and as readable as the `Array.prototype.concat()` one. Apart from that, the spread operator seems to be slightly faster based on [some benchmarks I have performed](https://jsben.ch/9txyg) (as of **Aug, 2020 on Google Chrome 84** - this might or might not be the case in the future, as new optimizations land in different browsers).
+
+However, `Array.prototype.concat()` can deal with non-array values better than the spread operator can, which might be something to consider when merging values that you are not certain are arrays:
+
+```js
+const a = [1, 2, 3];
+const b = true;
+const c = 'hi';
+
+const spreadAb = [...a, ...b]; // Error: b is not iterable
+const spreadAc = [...a, ...c]; // [1, 2, 3, 'h', 'i'], wrong result
+// You should use [...a, b] and [...a, c] instead
+
+const concatAb = [].concat(a, b); // [1, 2, 3, true]
+const concatAb = [].concat(a, c); // [1, 2, 3, 'hi']
+```
+
+As you can see in the above example, the spread operator either throws an error or doesn't output the correct result when passed a non-iterable object. `Array.prototype.concat()` on the other hand has no trouble being passed mixed input.
+
+So what's the verdict? Use the spread operator (`...`) whenever you know your inputs are arrays, as it performs better and is easy to read and understand. Favor `Array.prototype.concat()` when you are uncertain of one or more of the inputs and do not want to add additional checks, as it handles those cases more gracefully.
diff --git a/articles/snippets/javascript-modify-url-without-reload.md b/articles/snippets/javascript-modify-url-without-reload.md
new file mode 100644
index 000000000..cea26d067
--- /dev/null
+++ b/articles/snippets/javascript-modify-url-without-reload.md
@@ -0,0 +1,49 @@
+---
+title: How do I use JavaScript to modify the URL without reloading the page?
+shortTitle: Modify URL without reloading
+type: question
+tags: [javascript,browser]
+author: chalarangelo
+cover: compass
+excerpt: Learn all of the options JavaScript provides for modifying the URL of the current page in the browser without reloading the page.
+dateModified: 2021-09-27T16:47:49+03:00
+---
+
+### Using the History API
+
+The HTML5 [History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API) is definitely the way to go for modern websites. It accomplishes the task at hand, while also providing additional functionality. You can use either `history.pushState()` or `history.replaceState()` to modify the URL in the browser, depending on your needs:
+
+```js
+// Current URL: https://my-website.com/page_a
+const nextURL = 'https://my-website.com/page_b';
+const nextTitle = 'My new page title';
+const nextState = { additionalInformation: 'Updated the URL with JS' };
+
+// This will create a new entry in the browser's history, without reloading
+window.history.pushState(nextState, nextTitle, nextURL);
+
+// This will replace the current entry in the browser's history, without reloading
+window.history.replaceState(nextState, nextTitle, nextURL);
+```
+
+The arguments for both methods are the same, allowing you to pass a customized serializable `state` object as the first argument, a customized `title` (although most browsers will ignore this parameter) and the `URL` you want to add/replace in the browser's history. Bear in mind that the History API only allows same-origin URLs, so you cannot navigate to an entirely different website.
+
+### Using the Location API
+
+The older [Location API](https://developer.mozilla.org/en-US/docs/Web/API/Location) is not the best tool for the job. It reloads the page, but still allows you to modify the current URL and might be useful when working with legacy browsers. You can modify the URL, using either `Window.location.href`, `location.assign()` or `location.replace()`:
+
+```js
+// Current URL: https://my-website.com/page_a
+const nextURL = 'https://my-website.com/page_b';
+
+// This will create a new entry in the browser's history, reloading afterwards
+window.location.href = nextURL;
+
+// This will replace the current entry in the browser's history, reloading afterwards
+window.location.assign(nextURL);
+
+// This will replace the current entry in the browser's history, reloading afterwards
+window.location.replace(nextURL);
+```
+
+As you can see, all three options will cause a page reload, which can be undesirable. Unlike the History API, you can only set the URL, without any additional arguments. Finally, the Location API doesn't restrict you to same-origin URLs, which can cause security issues if you are not careful.
diff --git a/articles/snippets/javascript-module-cheatsheet.md b/articles/snippets/javascript-module-cheatsheet.md
new file mode 100644
index 000000000..c2545c599
--- /dev/null
+++ b/articles/snippets/javascript-module-cheatsheet.md
@@ -0,0 +1,139 @@
+---
+title: JavaScript modules Cheat Sheet
+type: cheatsheet
+tags: [javascript,cheatsheet]
+author: chalarangelo
+cover: mountain-lake-2
+excerpt: Learn everything you need to know about JavaScript modules with this handy cheatsheet.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Named exports
+
+```js
+/* environment.js */
+export const key = 'this-is-a-secret';
+
+/* index.js */
+import { key } from 'environment';
+```
+
+- Named exports use a name.
+- A module can have any number of named exports.
+- Import and export name should be the same.
+- Importing requires `{}`.
+
+### Default exports
+
+```js
+/* environment.js */
+const environment = {
+ key: 'this-is-a-secret',
+ port: 8000
+};
+
+export default environment;
+/* index.js */
+import environment from 'environment';
+
+const { key, port } = environment;
+```
+
+- Default exports expose a default value, use the `default` keyword.
+- A module can only have one default export.
+- Import name can be anything.
+- Importing does not require `{}`.
+
+### Default + named
+
+```js
+/* environment.js */
+export const envType = 'DEV';
+
+const environment = {
+ key: 'this-is-a-secret',
+ port: 8000
+};
+
+export default environment;
+
+/* index.js */
+import { envType }, environment from 'environment';
+
+const { key, port } = environment;
+```
+
+- Default and named exports can be mixed.
+- Rules about number of exports and naming conventions apply as before.
+- Import rules apply as before, can be mixed if necessary.
+
+### Export list
+
+```js
+/* environment.js */
+const key = 'this-is-a-secret';
+const port = 8000;
+
+export {
+ key,
+ port
+};
+
+/* index.js */
+import { key, port } from 'environment';
+```
+
+- An export list is a compact way to write multiple named exports.
+- Rules about number of exports, naming conventions and import rules are the same as those of named exports.
+- Export lists are not objects.
+
+### Rename export
+
+```js
+/* environment.js */
+const key = 'this-is-a-secret';
+
+export { key as authKey };
+
+/* index.js */
+import { authKey } from 'environment';
+```
+
+- Named exports can make use of the `as` keyword to rename an export.
+- Import name should be the same as the renamed export.
+
+### Rename import
+
+```js
+/* environment.js */
+export const key = 'this-is-a-secret';
+
+/* index.js */
+import { key as authKey } from 'environment';
+```
+
+- Named imports can make use of the `as` keyword to rename an import.
+- Import name (before the `as` keyword) should be the same as the export.
+
+### Import all
+
+```js
+/* environment.js */
+export const envType = 'DEV';
+
+const environment = {
+ key: 'this-is-a-secret',
+ port: 8000
+};
+
+export default environment;
+
+/* index.js */
+import * as env from 'environment';
+
+const { default: { key, port}, envType } = environment;
+```
+
+- Use `*` to import everything a module exports.
+- Named exports will be available by their names on the imported object.
+- Default export will be available as the `default` key on the imported object.
diff --git a/articles/snippets/javascript-naming-conventions.md b/articles/snippets/javascript-naming-conventions.md
new file mode 100644
index 000000000..74c93eda5
--- /dev/null
+++ b/articles/snippets/javascript-naming-conventions.md
@@ -0,0 +1,43 @@
+---
+title: JavaScript naming conventions
+shortTitle: Naming conventions
+type: story
+tags: [javascript,variable,cheatsheet]
+author: chalarangelo
+cover: naming-conventions
+excerpt: Naming conventions make code easier to read and understand. Learn how to name your variables in JavaScript with this handy guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Variables
+
+- Names are case-sensitive, lowercase and uppercase are different.
+- Start variable names with a letter, use `camelCase` for names.
+- Variable names should be self-descriptive, describing the stored value.
+- Boolean variables are usually prefixed with `is` or `has`.
+
+### Functions
+
+- Names are case-sensitive, lowercase and uppercase are different.
+- Start function names with a letter, use `camelCase` for names.
+- Use descriptive names, usually verbs in the imperative form.
+- Common prefixes are `get`, `make`, `apply` etc.
+- Class methods follow the same rules.
+
+### Constant
+
+- Names are case-sensitive, lowercase and uppercase are different.
+- Define constants at the top of your file, function or class.
+- Sometimes `UPPER_SNAKE_CASE` is used, while other times plain `camelCase`.
+
+### Classes
+
+- Names are case-sensitive, lowercase and uppercase are different.
+- Start class names with a capital letter, use `PascalCase` for names.
+- Use descriptive names, explaining the functionality of the class.
+- Components, which are used in frontend frameworks follow the same rules.
+
+### Private
+
+- Prefix any variable or function with `_` to show intention for it to be private.
+- As a convention, this will not prevent other parts of the code from accessing it.
diff --git a/articles/snippets/javascript-nullish-coalescing-optional-chaining.md b/articles/snippets/javascript-nullish-coalescing-optional-chaining.md
new file mode 100644
index 000000000..8a61b28f5
--- /dev/null
+++ b/articles/snippets/javascript-nullish-coalescing-optional-chaining.md
@@ -0,0 +1,58 @@
+---
+title: How can I use optional chaining and nullish coalescing in my JavaScript project?
+shortTitle: Optional chaining and nullish coalescing
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: purple-leaves
+excerpt: JavaScript ES2020 introduced optional chaining and nullish coalescing. Learn everything you need to know with this quick guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript ES2020 introduced some new features that help us write cleaner code. Let's take a quick look at two of them that aim to make working with objects and variables a lot easier.
+
+### Optional chaining
+
+The [optional chaining operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) (`?.`) allows us to access deeply nested object properties without having to validate each reference in the nesting chain. In case of a reference being nullish (`null` or `undefined`) the optional chaining operator will short-circuit, returning `undefined`. The optional chaining operator can also be used with function calls, returning `undefined` if the given function does not exist.
+
+The resulting code is shorter and simpler, as you can see below:
+
+```js
+const data = getDataFromMyAPI();
+
+// Without optional chaining
+const userName = data && data.user && data.user.name;
+const userType = data && data.user && data.user.type;
+data && data.showNotifications && data.showNotifications();
+
+// With optional chaining
+const userName = data?.user?.name;
+const userType = data?.user?.type;
+data.showNotifications?.();
+```
+
+### Nullish coalescing
+
+In the same spirit, the [nullish coalescing operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator) (`??`) is a logical operator that allows us to check for nullish (`null` or `undefined`) values, returning the right-hand side operand when the value is non-nullish, otherwise returning the left-hand side operand.
+
+Apart from cleaner code, this operator might spare us some headaches related to falsy values:
+
+```js
+const config = getServerConfig();
+
+// Without nullish coalescing
+const port = config.server.port || 8888;
+// Oops! This will be true even if we pass it false
+const wrongkeepAlive = config.server.keepAlive || true;
+// We'll have to explicitly check for nullish values
+const keepAlive =
+ (config.server.keepAlive !== null & config.server.keepAlive !== undefined)
+ ? config.server.keepAlive : true;
+
+// With nullish coalescing
+const port = config.server.port ?? 8888;
+// This works correctly
+const keepAlive = config.server.keepAlive ?? true;
+```
+
+**Note:** Keep in mind that both features are quite new, so their support might not be great just yet (around 80% at the time of writing [[1]](https://caniuse.com/#feat=mdn-javascript_operators_optional_chaining)[[2]](https://caniuse.com/#feat=mdn-javascript_operators_nullish_coalescing)).
diff --git a/articles/snippets/javascript-numeric-separator.md b/articles/snippets/javascript-numeric-separator.md
new file mode 100644
index 000000000..aded6caf2
--- /dev/null
+++ b/articles/snippets/javascript-numeric-separator.md
@@ -0,0 +1,30 @@
+---
+title: JavaScript's numeric separators explained
+shortTitle: Numeric separators explained
+type: story
+tags: [javascript,math,type]
+author: chalarangelo
+cover: coffee-drip
+excerpt: Numeric separators are a somewhat lesser-known JavaScript syntactic sugar that can make working with large constants a lot easier.
+dateModified: 2021-06-27T05:00:00-04:00
+---
+
+Numeric separators are a lesser-known JavaScript syntactic sugar that can make working with numeric constants a lot easier. The long and short of it is that you can add underscores (`_`) to numeric values to make them more readable.
+
+The idea of separating large numeric values with a special character might sound familiar on account of it being a syntax present in multiple other languages, such as Java, Python, Ruby etc. From what I can tell, numeric separators are at their best when creating shared constants that will not change and are very large, have many repeated digits and/or can be ambiguous.
+
+Apart from readability, numeric separators don't really offer anything else. For the sceptics among us that don't really see a lot of readability value either, I'd like to show two rather convincing sample cases:
+
+```js
+// How many zeroes is that? Millions? Billions? Trillions?
+const msInOneYear = 31536000000;
+// Is this 4,200 or 42.00 (in cents)?
+const price = 4200;
+
+// Ok, this is approximately 31.5 billion
+const msInOneYear = 31_536_000_000;
+// Based on the separator, this should be 42.00 (cents)
+const price = 42_00;
+```
+
+Finally, as far as caveats go, you only need to remember that numbers cannot start or end with a numeric separator and that you can't have two or more numeric separators in a row.
diff --git a/articles/snippets/javascript-object-array-proxy.md b/articles/snippets/javascript-object-array-proxy.md
new file mode 100644
index 000000000..66b7086a1
--- /dev/null
+++ b/articles/snippets/javascript-object-array-proxy.md
@@ -0,0 +1,124 @@
+---
+title: Can I use an object as an array without modifying it in JavaScript?
+shortTitle: Object as array
+type: question
+tags: [javascript,object,array,proxy,iterator,pattern]
+author: chalarangelo
+cover: birds
+excerpt: Learn how you can leverage the Proxy object to use a JavaScript object the same way as you would use a regular array.
+dateModified: 2021-09-27T16:42:11+03:00
+---
+
+The other day, I stumbled upon some code where I needed to handle an object as a regular array a few times. This was, of course, achievable using `Object.keys()`, `Object.values()` or `Object.entries()`, but it started getting verbose real quick.
+
+So I thought I could create some kind of wrapper that would take an object and define some array-like behavior for it. I was mainly in need of `Array.prototype.map()`, `Array.prototype.find()`, `Array.prototype.includes()` and `Array.prototype.length`. All of this functionality was pretty straightforward to create using `Object` methods. The only tricky part, so to speak, was getting the object to behave as an iterable, which required using the `Symbol.iterator` and a generator function.
+
+Injecting the new functionality into an object could be as simple as adding the methods to it. The downside of this approach is that they would be part of the actual object, which can be problematic. It also doesn't help that this is not very reusable if we want to apply this over a handful of objects.
+
+Enter the [Proxy object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy), one of the lesser known tools in a JavaScript developer's tool belt, yet a very powerful one. It's used to intercept certain operations for an object, such as property lookup, assignment etc. In this scenario, it can neatly wrap the required functionality into a function that creates a proxy around the object.
+
+The final code, long as it may be, can be seen in the example below. It implements the functionality I needed, as well as a handful more `Array` methods for good measure:
+
+```js
+const toKeyedArray = obj => {
+ const methods = {
+ map(target) {
+ return callback =>
+ Object.keys(target).map(key => callback(target[key], key, target));
+ },
+ reduce(target) {
+ return (callback, accumulator) =>
+ Object.keys(target).reduce(
+ (acc, key) => callback(acc, target[key], key, target),
+ accumulator
+ );
+ },
+ forEach(target) {
+ return callback =>
+ Object.keys(target).forEach(key => callback(target[key], key, target));
+ },
+ filter(target) {
+ return callback =>
+ Object.keys(target).reduce((acc, key) => {
+ if (callback(target[key], key, target)) acc[key] = target[key];
+ return acc;
+ }, {});
+ },
+ slice(target) {
+ return (start, end) => Object.values(target).slice(start, end);
+ },
+ find(target) {
+ return callback => {
+ return (Object.entries(target).find(([key, value]) =>
+ callback(value, key, target)
+ ) || [])[0];
+ };
+ },
+ findKey(target) {
+ return callback =>
+ Object.keys(target).find(key => callback(target[key], key, target));
+ },
+ includes(target) {
+ return val => Object.values(target).includes(val);
+ },
+ keyOf(target) {
+ return value =>
+ Object.keys(target).find(key => target[key] === value) || null;
+ },
+ lastKeyOf(target) {
+ return value =>
+ Object.keys(target)
+ .reverse()
+ .find(key => target[key] === value) || null;
+ },
+ };
+ const methodKeys = Object.keys(methods);
+
+ const handler = {
+ get(target, prop, receiver) {
+ if (methodKeys.includes(prop)) return methods[prop](...arguments);
+ const [keys, values] = [Object.keys(target), Object.values(target)];
+ if (prop === 'length') return keys.length;
+ if (prop === 'keys') return keys;
+ if (prop === 'values') return values;
+ if (prop === Symbol.iterator)
+ return function* () {
+ for (value of values) yield value;
+ return;
+ };
+ else return Reflect.get(...arguments);
+ },
+ };
+
+ return new Proxy(obj, handler);
+};
+
+// Object creation
+const x = toKeyedArray({ a: 'A', b: 'B' });
+
+// Accessing properties and values
+x.a; // 'A'
+x.keys; // ['a', 'b']
+x.values; // ['A', 'B']
+[...x]; // ['A', 'B']
+x.length; // 2
+
+// Inserting values
+x.c = 'c'; // x = { a: 'A', b: 'B', c: 'c' }
+x.length; // 3
+
+// Array methods
+x.forEach((v, i) => console.log(`${i}: ${v}`)); // LOGS: 'a: A', 'b: B', 'c: c'
+x.map((v, i) => i + v); // ['aA', 'bB, 'cc]
+x.filter((v, i) => v !== 'B'); // { a: 'A', c: 'c' }
+x.reduce((a, v, i) => ({ ...a, [v]: i }), {}); // { A: 'a', B: 'b', c: 'c' }
+x.slice(0, 2); // ['A', 'B']
+x.slice(-1); // ['c']
+x.find((v, i) => v === i); // 'c'
+x.findKey((v, i) => v === 'B'); // 'b'
+x.includes('c'); // true
+x.includes('d'); // false
+x.keyOf('B'); // 'b'
+x.keyOf('a'); // null
+x.lastKeyOf('c'); // 'c'
+```
diff --git a/articles/snippets/javascript-object-comparison.md b/articles/snippets/javascript-object-comparison.md
new file mode 100644
index 000000000..f0c37f621
--- /dev/null
+++ b/articles/snippets/javascript-object-comparison.md
@@ -0,0 +1,69 @@
+---
+title: How do I compare two objects in JavaScript?
+shortTitle: Object comparison
+type: question
+tags: [javascript,object,comparison]
+author: chalarangelo
+cover: blue-lake
+excerpt: Learn how you can compare two objects in JavaScript using various different techniques.
+dateModified: 2021-09-26T05:00:00-04:00
+---
+
+### Equality comparison
+
+Even though two different objects can have the same properties with equal values, they are not considered equal when compared using either the loose or strict equality operators (`==` or `===`). This is because arrays and objects in JavaScript are compared by reference. This is unlike primitive values which are compared by value.
+
+```js
+const a = { name: 'John', age: 26 };
+const b = { name: 'John', age: 26 };
+
+a === b; // false
+```
+
+### JSON.stringify
+
+`JSON.stringify()` often comes up as the solution to this problem. While it can be useful in some situations, comparing the serialized strings can have its own pitfalls. The most common of these has to do with similar, but not equal, values that result in the same serialized string.
+
+```js
+const equals = (a, b) => JSON.stringify(a) === JSON.stringify(b);
+
+const a = { name: 'John', age: 26 };
+const b = { name: 'John', age: 26 };
+
+equals(a, b); // true
+
+const c = { name: 'John' };
+const d = { name: 'John', age: undefined };
+
+equals(c, d); // true, should be false
+```
+
+### Deep equality comparison
+
+As it turns out, comparing two objects is not trivial. This is the reason why shallow or deep equality comparison helper functions are so common. These usually use recursion to deeply compare two objects, accounting for most scenarios such as empty values, special types and nesting.
+
+```js
+const equals = (a, b) => {
+ if (a === b) return true;
+ if (a instanceof Date && b instanceof Date)
+ return a.getTime() === b.getTime();
+ if (!a || !b || (typeof a !== 'object' && typeof b !== 'object'))
+ return a === b;
+ if (a.prototype !== b.prototype) return false;
+ const keys = Object.keys(a);
+ if (keys.length !== Object.keys(b).length) return false;
+ return keys.every(k => equals(a[k], b[k]));
+};
+
+const a = { name: 'John', age: 26 };
+const b = { name: 'John', age: 26 };
+
+equals(a, b); // true
+
+const c = { name: 'John' };
+const d = { name: 'John', age: undefined };
+
+equals(c, d); // false
+```
+
+The above helper function handles all of these issues and is explained in more depth in the [equals snippet](/js/s/equals).
diff --git a/articles/snippets/javascript-object-is-triple-equals.md b/articles/snippets/javascript-object-is-triple-equals.md
new file mode 100644
index 000000000..016743b4c
--- /dev/null
+++ b/articles/snippets/javascript-object-is-triple-equals.md
@@ -0,0 +1,30 @@
+---
+title: What's the difference between Object.is() and the triple equals operator in JavaScript?
+shortTitle: Object.is() vs triple equals operator
+type: question
+tags: [javascript,object,type]
+author: chalarangelo
+cover: rocky-mountains
+excerpt: "`Object.is()` and the triple equals operator (`===`) can both be used for equality checking in JavaScript, but when should you use each one?"
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+If you want to check equality in JavaScript, there are two comparison operators, which are explained in depth in a previous [article](/blog/s/javascript-equality).
+
+Very briefly, the double equals operator (`==`) only compares value whereas the triple equals operator (`===`) compares both value and type. But there is also a third option, `Object.is()`, which behaves the same as the triple equals operator with the exception of `NaN` and `+0` and `-0`.
+
+Here are some examples for additional clarity:
+
+```js
+{} === {}; // false
+Object.is({}, {}); // false
+
+1 === 1; // true
+Object.is(1, 1); // true
+
++0 === -0; // true
+Object.is(+0, -0); // false
+
+NaN === NaN; // false
+Object.is(NaN, NaN); // true
+```
diff --git a/articles/snippets/javascript-pass-by-reference-or-pass-by-value.md b/articles/snippets/javascript-pass-by-reference-or-pass-by-value.md
new file mode 100644
index 000000000..6a30d0337
--- /dev/null
+++ b/articles/snippets/javascript-pass-by-reference-or-pass-by-value.md
@@ -0,0 +1,39 @@
+---
+title: Is JavaScript pass-by-value or pass-by-reference?
+shortTitle: Pass-by-value or pass-by-reference
+type: question
+tags: [javascript,function,object]
+author: chalarangelo
+cover: baloons-field
+excerpt: How JavaScript handles passing data is a source of confusion and bugs for many developers, especially when it comes to object types.
+dateModified: 2021-12-05T05:00:00-04:00
+---
+
+JavaScript is always **pass-by-value**. This means everything in JavaScript is a value type and function arguments are always passed by value. That being said, object types are a bit more confusing.
+
+The confusion lies in the fact that **object types are reference types** which are passed by value. As weird as this sounds, a reference to an object is passed to a function by value. The subtle difference here lies in the fact that an object reference passed by value is not the same as passing an object by reference.
+
+Simply put, changes to the object inside the function will affect the original object, as they both refer to the same object. However, reassigning the value of the variable holding the object originally will not affect the object referenced by the function. Let me demonstrate this with an example:
+
+```js
+let myObj = { a: 1 };
+const myFunc = obj => {
+ obj.a++;
+ return obj;
+}
+let otherObj = myFunc(myObj);
+
+myObj; // { a: 2 }
+otherObj; // { a: 2 }
+myObj === otherObj; // true
+
+myObj = { a: 4, b: 0 };
+
+myObj; // { a: 4, b: 0 }
+otherObj; // { a: 2 }
+myObj === otherObj; // false
+```
+
+In this example, `myObj` is a plain JavaScript object, passed as an argument to `myFunc`. The `obj` argument inside `myFunc` is a reference to the same object, `myObj`. Any changes made to `obj` affect `myObj`, as they are the exact same object. This means that assigning the result (`obj`) of the function call to another variable, `otherObj`, will pass the same reference to the variable. The result is that both `myObj` and `otherObj` reference the same object value.
+
+Reassigning `myObj` to a new object value does not affect `otherObj` at all. `otherObj` still references the original object. If JavaScript was pass-by-reference, reassigning `myObj` would affect `otherObj`, which is clearly not the case.
diff --git a/articles/snippets/javascript-prefix-postfix-operators.md b/articles/snippets/javascript-prefix-postfix-operators.md
new file mode 100644
index 000000000..4c4b946dc
--- /dev/null
+++ b/articles/snippets/javascript-prefix-postfix-operators.md
@@ -0,0 +1,28 @@
+---
+title: What is the difference between prefix and postfix operators?
+shortTitle: Prefix and postfix operators
+type: question
+tags: [javascript,math]
+author: chalarangelo
+cover: plant-candle
+excerpt: While both the prefix and postfix operators increment a value, the resulting value of the expression is very different.
+dateModified: 2021-10-31T05:00:00-04:00
+---
+
+The increment operator (`++`) adds `1` to its operand and returns a value. Similarly, the decrement operator (`--`) subtracts `1` from its operand and returns a value. Both of these operators can be used either prefix (`++i`, `--i`) or postfix (`i++`, `i--`).
+
+If used prefix, the value is incremented/decremented, and the value of the expression is the updated value.
+
+```js
+let i = 0; // i = 0
+let j = ++i; // i = 1, j = 1
+let k = --i; // i = 0, k = 0
+```
+
+If used postfix, the value is incremented/decremented, and the value of the expression is the original value.
+
+```js
+let i = 0; // i = 0
+let j = i++; // i = 1, j = 0
+let k = i--; // i = 0, k = 1
+```
diff --git a/articles/snippets/javascript-pretty-print-json.md b/articles/snippets/javascript-pretty-print-json.md
new file mode 100644
index 000000000..59b90d6d1
--- /dev/null
+++ b/articles/snippets/javascript-pretty-print-json.md
@@ -0,0 +1,58 @@
+---
+title: "Tip: Pretty-print a JSON object with JavaScript"
+shortTitle: Pretty-print JSON
+type: tip
+tags: [javascript,object,json]
+author: chalarangelo
+cover: memories-of-pineapple-3
+excerpt: Pretty-printing JSON objects in pretty easy and customizable in JavaScript. Here's the gist of it.
+dateModified: 2022-07-30T05:00:00-04:00
+---
+
+Pretty-printing refers to the process of making some data more human-readable. In regards to JSON, it's primarily the process of indenting the data so that it is easier to read. This is pretty easy to accomplish, using `JSON.stringify()` with the appropriate arguments.
+
+```js
+const obj = {
+ id: 1182,
+ username: 'johnsmith',
+ active: true,
+ emails: ['johnsmith@mysite.com', 'contact@johnsmi.th'],
+};
+
+JSON.stringify(obj, null, 2);
+// {
+// "id": 1182,
+// "username": "johnsmith",
+// "active": true,
+// "emails": [
+// "johnsmith@mysite.com"
+// "contact@johnsmi.th"
+// ]
+// }
+```
+
+As you can see in this example, the third argument of `JSON.stringify()` is the number of spaces to indent each level of the object. Additionally, you can use the second argument to specify a replacer function. This can come in handy if you want to provide custom formatting for certain types of values or specific key-value pairs.
+
+```js
+const obj = {
+ id: 1182,
+ username: 'johnsmith',
+ active: true,
+ emails: ['johnsmith@mysite.com', 'contact@johnsmi.th'],
+};
+
+const replacer = (key, value) => {
+ if (key === 'id') return value.toString(16);
+ if (key === 'username') return `@${value}`;
+ if (key === 'emails') return `${value[0]} +${value.length - 1} more`;
+ return value;
+};
+
+JSON.stringify(obj, replacer, 2);
+// {
+// "id": "0x4e2",
+// "username": "@johnsmith",
+// "active": true,
+// "emails": "johnsmith@mysite.com +1 more"
+// }
+```
diff --git a/articles/snippets/javascript-prevent-string-being-escaped.md b/articles/snippets/javascript-prevent-string-being-escaped.md
new file mode 100644
index 000000000..1610b9f34
--- /dev/null
+++ b/articles/snippets/javascript-prevent-string-being-escaped.md
@@ -0,0 +1,18 @@
+---
+title: "Tip: Prevent a string from being escaped in JavaScript"
+shortTitle: Prevent string escaping
+type: tip
+tags: [javascript,string]
+author: chalarangelo
+cover: glass-blowing
+excerpt: Strings in JavaScript can be escaped in various ways. But how do you prevent a string from being escaped? Here's a handy trick for that.
+dateModified: 2021-06-17T12:00:00+03:00
+---
+
+By default, when JavaScript sees an escape character (`\`), it will escape the character after it. However, there are cases where you might not want this behavior (e.g. when you want to store a Windows path as a string). For these cases, you can use a template literal and the `String.raw()` tag function:
+
+```js
+const path = `C:\web\index.html`; // 'C:web.html'
+
+const unescapedPath = String.raw`C:\web\index.html`; // 'C:\web\index.html'
+```
diff --git a/articles/snippets/javascript-primitive-instanceof.md b/articles/snippets/javascript-primitive-instanceof.md
new file mode 100644
index 000000000..2adf78676
--- /dev/null
+++ b/articles/snippets/javascript-primitive-instanceof.md
@@ -0,0 +1,51 @@
+---
+title: Is there a way to use instanceof for primitive JavaScript values?
+shortTitle: Using instanceof for primitive values
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: wooden-bowl
+excerpt: JavaScript's `instanceof` operator can't be used with primitive values, but there are a some tricks that you can leverage to your advantage.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript provides two operators for typechecking:
+
+- `typeof` is used to typecheck for primitive values
+- `instanceof` is used to typecheck for class instances
+
+Primitive values can't leverage the `instanceof` operator, which is a bit of a letdown. To make matters worse, JavaScript's built-in objects such as `Boolean`, `String` and `Number` can only be used with `instanceof` to check for instances created using the corresponding constructor. Moreover, `typeof` has a few quirks that further complicate matters, such as `typeof null` returning `'object'`.
+
+Yet, there's still hope to use `instanceof` for primitive values. [`Symbol.hasInstance`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance) allows us to customize the behavior of the `instanceof` operator. But, in order to do that, we need to define a `class` for each primitive type. Here's what this looks like:
+
+```js
+class PrimitiveNumber {
+ static [Symbol.hasInstance] = x => typeof x === 'number';
+}
+123 instanceof PrimitiveNumber; // true
+
+class PrimitiveString {
+ static [Symbol.hasInstance] = x => typeof x === 'string';
+}
+'abc' instanceof PrimitiveString; // true
+
+class PrimitiveBoolean {
+ static [Symbol.hasInstance] = x => typeof x === 'boolean';
+}
+false instanceof PrimitiveBoolean; // true
+
+class PrimitiveSymbol {
+ static [Symbol.hasInstance] = x => typeof x === 'symbol';
+}
+Symbol.iterator instanceof PrimitiveSymbol; // true
+
+class PrimitiveNull {
+ static [Symbol.hasInstance] = x => x === null;
+}
+null instanceof PrimitiveNull; // true
+
+class PrimitiveUndefined {
+ static [Symbol.hasInstance] = x => x === undefined;
+}
+undefined instanceof PrimitiveUndefined; // true
+```
diff --git a/articles/snippets/javascript-promise-then-catch.md b/articles/snippets/javascript-promise-then-catch.md
new file mode 100644
index 000000000..8bf49b8e9
--- /dev/null
+++ b/articles/snippets/javascript-promise-then-catch.md
@@ -0,0 +1,25 @@
+---
+title: "Tip: The order of then and catch matters"
+shortTitle: The order of then and catch matters
+type: tip
+tags: [javascript,function,promise]
+author: chalarangelo
+cover: blue-sunrise
+excerpt: Messing up the order of chained `then` and `catch` methods in JavaScript promises can cause problems. Here's a short primer on the subject.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Many if not most promise-related headaches come from incorrectly ordered `Promise.prototype.then()` and `Promise.prototype.catch()` methods. The order in which these methods are chained to a promise can lead to very different behaviors. Let's take a look at a very simple example:
+
+```js
+const myPromise = () => Promise.reject('Oops!');
+const logger = data => console.log(data);
+const identity = data => data;
+
+myPromise().catch(identity).then(logger); // LOGS: Oops!
+myPromise().then(logger).catch(identity); // Nothing is logged
+```
+
+As you can see from this example, swapping the `catch()` and `then()` methods results in entirely different behavior, even though the promise has the same result. This is due to the fact that each chained method will result itself in a promise. This means that the first one will pass its result to the second, the second to the third and so on and so forth. While this might seem obvious when looking at an example like this one, many times it's overlooked and can result in hard to debug issues. This is especially true when the promise chain is long and complicated.
+
+So, next time you are working with promises, try to think of `then()` and `catch()` methods in terms of promise chaining and remember that order matters!
diff --git a/articles/snippets/javascript-promise-then-finally.md b/articles/snippets/javascript-promise-then-finally.md
new file mode 100644
index 000000000..6ef3633c7
--- /dev/null
+++ b/articles/snippets/javascript-promise-then-finally.md
@@ -0,0 +1,46 @@
+---
+title: What is the difference between then and finally in a JavaScript promise?
+shortTitle: Promise then vs finally
+type: question
+tags: [javascript,function,promise]
+author: chalarangelo
+cover: blue-sunrise
+excerpt: A JavaScript promise's `then` and `finally` methods seem very similar. But there are a few important differences you need to keep in mind.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+On the surface, `Promise.prototype.then()` and `Promise.prototype.finally()` seem very similar. But there are a few important differences you need to keep in mind.
+
+The first and most obvious one is that `finally()` doesn't receive the resulting value of the promise chain. On the same note, as no value is received by `finally()`, the resolved value of the promise can't be changed as well.
+
+```js
+new Promise((resolve, reject) => resolve(10))
+ .then(x => {
+ console.log(x); // 10
+ return x + 1;
+ })
+ .finally(x => {
+ console.log(x); // undefined
+ return x + 2;
+ });
+// Promise resolves to 11, the return value of then()
+```
+
+Another difference is related to error handling and how the promise chain is resolved. Sometimes, you might want to defer catching an error in the promise chain, allowing you to handle them elsewhere. In this case, a chained `then()` will not be executed, whereas `finally()` will. Moreover, if a previous `catch()` throws, you end up in the same situation.
+
+```js
+new Promise((resolve, reject) => reject(0))
+ .catch(x => {
+ console.log(x); // 0
+ throw x;
+ })
+ .then(x => {
+ console.log(x); // Will not run
+ })
+ .finally(() => {
+ console.log('clean up'); // 'clean up'
+ });
+// Uncaught (in promise) 0
+```
+
+The takeaway here is that you shouldn't substitute `then()` and `finally()` unless there is a very specific reason to do so. As a rule of thumb, `finally()` should be used for cleaning up (clearing timeouts, nulling references, resetting UI state etc.).
diff --git a/articles/snippets/javascript-promises.md b/articles/snippets/javascript-promises.md
new file mode 100644
index 000000000..23b996443
--- /dev/null
+++ b/articles/snippets/javascript-promises.md
@@ -0,0 +1,29 @@
+---
+title: What are promises in JavaScript? In which states can a promise be?
+shortTitle: Promises introduction
+type: question
+tags: [javascript,function,promise]
+author: chalarangelo
+cover: sail-away
+excerpt: JavaScript's promises represent the eventual completion (or failure) of asynchronous operations and their resulting value.
+dateModified: 2021-10-24T05:00:00-04:00
+---
+
+The `Promise` object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value. A common example of using promises would be fetching data from a URL. This would create a `Promise` object that represents the data we expect to receive. For example:
+
+```js
+fetch('https://my.api.com/items/1')
+ .catch(err => console.log(`Failed with error: ${err}`))
+ .then(response => response.json())
+ .then(json => console.log(json));
+```
+
+The tricky part about promises is understanding that the resulting value may not initially be available. Instead, the promise can be in one of three states:
+
+- **Pending:** initial state, neither fulfilled nor rejected.
+- **Fulfilled:** meaning that the operation was completed successfully.
+- **Rejected:** meaning that the operation failed.
+
+A pending `Promise` can either be fulfilled with a value or rejected with a reason (error). When either of these happens, the associated handlers (`Promise.prototype.then()`, `Promise.prototype.catch()`) are called.
+
+In the previous example, the `Promise` starts in a pending state, until a response from the server is received. If anything goes wrong during that time, the `Promise` will be rejected and the `Promise.prototype.catch()` handler will log the error to the console. Otherwise, the `Promise` will be fulfilled and the first `Promise.prototype.then()` handler will execute, returning itself a new `Promise`. The new promise will be fulfilled and call the second `Promise.prototype.then()` handler to log the parsed JSON data to the console.
diff --git a/articles/snippets/javascript-property-enumerability.md b/articles/snippets/javascript-property-enumerability.md
new file mode 100644
index 000000000..302affca2
--- /dev/null
+++ b/articles/snippets/javascript-property-enumerability.md
@@ -0,0 +1,37 @@
+---
+title: JavaScript property enumerability
+shortTitle: Property enumerability
+type: story
+tags: [javascript,object]
+author: chalarangelo
+cover: old-consoles
+excerpt: Property enumerability dictates how JavaScript object properties behave in different scenarios.
+dateModified: 2022-09-11T05:00:00-04:00
+---
+
+In most cases, object properties are enumerable by default, unless they are Symbols. This means that you can use the `for...in` loop to iterate over the properties of an object. Similarly, enumerable properties appear in object methods that enumerate the properties of an object. An example of this is the `Object.keys()` method, which will omit properties that are not enumerable. Finally, when using the object spread operator (`...`), only enumerable properties are copied to the new object.
+
+```js
+const person = {
+ name: 'John',
+ surname: 'Doe',
+ age: 30,
+ socialSecurityNumber: '123-45-6789',
+};
+
+Object.defineProperty(person, 'socialSecurityNumber', {
+ enumerable: false,
+});
+
+person.hasOwnProperty('socialSecurityNumber'); // true
+person.propertyIsEnumerable('socialSecurityNumber'); // false
+
+Object.keys(person); // ['name', 'surname', 'age']
+Object.getOwnPropertyNames(person);
+// ['name', 'surname', 'age', 'socialSecurityNumber']
+
+const clone = { ...person };
+clone.socialSecurityNumber; // undefined
+```
+
+To create a non-enumerable property, you can use `Object.defineProperty()` with the appropriate descriptor. You can check for the property's existence, using `Object.prototype.hasOwnProperty()` and for its enumerability, using `Object.prototype.propertyIsEnumerable()`. Additionally, in contrast to Symbols, non-enumerable properties will show up when using `Object.getOwnPropertyNames()`.
diff --git a/articles/snippets/javascript-pure-functions.md b/articles/snippets/javascript-pure-functions.md
new file mode 100644
index 000000000..018fb25f3
--- /dev/null
+++ b/articles/snippets/javascript-pure-functions.md
@@ -0,0 +1,35 @@
+---
+title: What is a pure function?
+shortTitle: Pure function introduction
+type: question
+tags: [javascript,function]
+author: chalarangelo
+cover: dark-leaves
+excerpt: Pure functions are a very important concept to know, especially if you're interested in functional programming.
+dateModified: 2021-12-19T05:00:00-04:00
+---
+
+Pure functions are one of the most important concepts to learn and understand, especially if you're interested in functional programming.
+
+A pure function is a function that satisfies the following two conditions:
+
+- Given the same input, it always returns the same output.
+- Causes no side effects outside the function's scope.
+
+Let's look at some examples of pure and impure functions:
+
+```js
+// Pure
+const add = (x, y) => x + y;
+const concat = (arr, value) => [...arr, value];
+const order = arr => [...arr].sort((a, b) => a - b);
+
+// Impure
+const addRandom = x => x + Math.random();
+const pushConcat = (arr, value) => { arr.push(value); return arr; }
+const reorder = arr => arr.sort((a, b) => a - b);
+```
+
+Understanding if a function is pure or impure is generally pretty easy. An easy trick to tell if a function is impure is if it makes sense to call it without using its return value or if it doesn't return any. These usually indicate that a function causes side effects.
+
+Pure functions are more reliable and reusable, which in turn makes them easier to reason about. It's usually preferable to use a pure function over an impure one if constraints allow it.
diff --git a/articles/snippets/javascript-query-selector-shorthand.md b/articles/snippets/javascript-query-selector-shorthand.md
new file mode 100644
index 000000000..6a71adc7e
--- /dev/null
+++ b/articles/snippets/javascript-query-selector-shorthand.md
@@ -0,0 +1,20 @@
+---
+title: "Tip: Create your own query selector shorthand"
+shortTitle: Query selector shorthand
+type: tip
+tags: [javascript,browser]
+author: chalarangelo
+cover: pineapple-at-work
+excerpt: Ever wanted to create your own jquery-like query selector shorthand? Here's how!
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Most of us are familiar with jquery and probably quite a few of us are familiar with the Chrome console's `$` and `$$` shorthands for query selectors. I recently figured out a way to replicate these shorthands in my code, using `Document.querySelector()`, `Document.querySelectorAll()` and `Function.prototype.bind()`. Here's how to do it, just make sure you don't mix them up with jquery if you are still using it:
+
+```js
+const $ = document.querySelector.bind(document);
+const $$ = document.querySelectorAll.bind(document);
+
+const mainContent = $('.main-content');
+const externalLinks = $$('a[target="_blank"]');
+```
diff --git a/articles/snippets/javascript-random-value-pure-functions.md b/articles/snippets/javascript-random-value-pure-functions.md
new file mode 100644
index 000000000..2af13f6b7
--- /dev/null
+++ b/articles/snippets/javascript-random-value-pure-functions.md
@@ -0,0 +1,32 @@
+---
+title: Using random values with pure functions
+shortTitle: Pure functions & randomness
+type: story
+tags: [javascript,function,random,testing]
+author: chalarangelo
+cover: do-more-computer
+excerpt: Randomness and pure functions don't seem to go hand in hand. But where there's a will, there's a way.
+dateModified: 2022-06-19T05:00:00-04:00
+---
+
+Working with random values can create code that's hard to test. Usually, the remedy to such issues is to use [pure functions](/articles/javascript-pure-functions). A pure function is a function that always returns the same value given the same input. As they do not have side effects and their return value is predictable, testing pure functions is much easier.
+
+```js
+// An impure function that returns a random value
+const getNumber = (min = 0, max = 1) =>
+ Math.max(Math.min(Math.random(), max), min);
+```
+
+From the definition alone, pure functions and random values don't sound very compatible. After all, randomness inherently means unpredictability. The naive approach would be to move the randomness outside of the function and pass the generated value as an argument to it. This would only hide the issue without fixing it let alone require a lot of refactoring to work.
+
+The approach to use the function's arguments is on the right track, though. The key is that function arguments can be omitted, allowing us to specify default values for them. This allows us to pass a random value as an argument to the function, and the function will use the default value if the argument is omitted.
+
+But how can we actually pass a random value as a default argument to a function? Luckily for us, JavaScript defers evaluation of function arguments to the time of function invocation. This means that we can use `Math.random()` to generate a random value, and pass it as the default argument to the function.
+
+```js
+// A pure function that returns a random value
+const getNumber = (min = 0, max = 1, num = Math.random()) =>
+ Math.max(Math.min(num, max), min);
+```
+
+By making this simple change, you can avoid a lot of headaches for you and your team. Using a function such as `Math.random()` as the default argument will require minimal refactoring and make your code easier to test.
diff --git a/articles/snippets/javascript-range-generator.md b/articles/snippets/javascript-range-generator.md
new file mode 100644
index 000000000..e23edea98
--- /dev/null
+++ b/articles/snippets/javascript-range-generator.md
@@ -0,0 +1,67 @@
+---
+title: Using JavaScript generator functions for ranges
+shortTitle: Generator functions for ranges
+type: story
+tags: [javascript,function,array]
+author: chalarangelo
+cover: generator
+excerpt: Learn how to use JavaScript ES6 generators and iterators to iterate over ranges of numbers.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Generator functions
+
+[JavaScript ES6 generators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) allow you to define functions that can be exited and later re-entered, while retaining their context (variable bindings). They are defined using `function*` (`function` keyword followed by an asterisk) and use `yield` expressions to return their result. For example:
+
+```js
+function* generateRange(end, start = 0, step = 1) {
+ let x = start - step;
+ while(x < end - step) yield x += step;
+}
+
+const gen5 = generateRange(5);
+let x = gen5.next();
+
+while (!x.done) {
+ console.log(x.value);
+ x = gen5.next();
+} // Logs: 0, 1, 2, 3, 4
+```
+
+In the above example, we define a generator function, `generateRange`, which will return each value between `start` and `end`, incrementing by `step` each time. We use the [generator object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator) to call `Generator.prototype.next()` until it returns `{value: undefined, done: true}` to iterate over the values the generator produces.
+
+### Symbol.iterator
+
+[`Symbol.iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator) specifies the default iterator for an object. Oftentimes, `Symbol.iterator` is implemented using a generator function. For example:
+
+```js
+const iterableXx = {
+ [Symbol.iterator]: function* () {
+ yield 1;
+ yield 2;
+ }
+};
+
+console.log([...iterableX]); // [1, 2]
+```
+
+As you can see in this example, the object is made iterable by assigning a generator function to its `Symbol.iterator` property. This can come especially handy, if you want to iterate over some arbitrary data or create an object that is iterable and uses a generator function under the hood.
+
+### Putting it all together
+
+Knowing how both concepts work, we can combine them to create a range generator, similar to Python or Ruby's ranges:
+
+```js
+const range = (end, start = 0, step = 1) => {
+ function* generateRange() {
+ let x = start - step;
+ while(x < end - step) yield x += step;
+ }
+ return {
+ [Symbol.iterator]: generateRange
+ };
+}
+
+console.log([...range(7)]); // [0, 1, 2, 3, 4, 5, 6]
+for (let i of range(8, 2, 2)) console.log(i); // Logs: 2, 4, 6
+```
diff --git a/articles/snippets/javascript-recursion.md b/articles/snippets/javascript-recursion.md
new file mode 100644
index 000000000..abe944c57
--- /dev/null
+++ b/articles/snippets/javascript-recursion.md
@@ -0,0 +1,27 @@
+---
+title: What is recursion and when is it useful?
+shortTitle: Recursion introduction
+type: question
+tags: [javascript,function,recursion]
+author: chalarangelo
+cover: curve
+excerpt: Recursion is a very important programming concept all developers should be familiar with.
+dateModified: 2022-01-23T05:00:00-04:00
+---
+
+Recursion is the **repeated application of a process**. In JavaScript, recursion involves functions that call themselves repeatedly until they reach a base case. The base case breaks out of the recursion loop, thus allowing previous calls to the function to return a result. If no such case exists, the function will call itself indefinitely resulting in a stack overflow.
+
+Recursion is used to solve problems where the solution depends on solutions to smaller instances of the same problem. A commonly-used example of a problem that can be solved recursively is the Fibonacci sequence:
+
+```js
+const fibonacci = n => {
+ if (n <= 1) return n;
+ return fibonacci(n - 1) + fibonacci(n - 2);
+};
+
+fibonacci(6); // 8
+```
+
+The base case for this example is `n` being less than or equal to `1`, where the function returns the value of `n`. Any other value will call the `fibonacci` function twice to compute the values of `n - 1` and `n - 2`. These will in turn call the `fibonacci` function again until the base case is reached.
+
+While the Fibonacci sequence can be solved with recursion, it can be more efficient to solve it using iteration. However, the inverse is true for a lot of other problems where identifying and indexing the sub-problems is difficult or costly.
diff --git a/articles/snippets/javascript-reload-page.md b/articles/snippets/javascript-reload-page.md
new file mode 100644
index 000000000..37d62567f
--- /dev/null
+++ b/articles/snippets/javascript-reload-page.md
@@ -0,0 +1,46 @@
+---
+title: How can I use JavaScript to reload the page?
+shortTitle: Reload page
+type: story
+tags: [javascript,browser]
+author: chalarangelo
+cover: night-tram
+excerpt: Need to reload the current page using JavaScript? Here's the best way to do it, as well as some alternatives.
+dateModified: 2023-05-14T05:00:00-04:00
+---
+
+### The short answer
+
+Most often than not, `window.location.reload()` is all you need to reload the current page. This method behaves exactly like the **browser's reload button**, using the same cache rules and everything.
+
+```js
+// Reload the page
+window.location.reload();
+```
+
+### The slightly longer answer
+
+While `window.location.reload()` is the most common way to reload a page, there are some nuances that you might need to be aware of.
+
+As stated already, compatibility shouldn't be an issue, so we're not going to delve into that. However, there's a notable oddity concerning the method's arguments. As it turns out, **Firefox** used to support an optional `forceGet` boolean argument, which you might come across in older code. This means that passing a value of `true` to the method would bypass the **browser's cache**.
+
+```js
+// Bypass cache in Firefox
+window.location.reload(true);
+```
+
+Apart from that, `window.location.reload()` will reload the page **keeping POST data** in forms, which might not be desired. In those situations, you might want to assign `window.location.href` to itself to cause a reload. This will cause the page to reload, but will also clear the POST data.
+
+```js
+// Clear POST data
+window.location.href = window.location.href;
+```
+
+This technique also comes with some caveats. For example, if the current **URL contains a hash**, the page won't reload. In this case, you might want to use `String.prototype.split()` to remove the hash from the URL and then assign it to itself.
+
+```js
+// Reload the page, removing the hash from the URL
+window.location.href = window.location.href.split('#')[0];
+```
+
+As you can see, each technique has its pros and cons, so you should choose the one that best suits your needs. That being said, `window.location.reload()` is the most common and reliable way to reload a page, so it's the one you should use most of the time.
diff --git a/articles/snippets/javascript-remove-object-property.md b/articles/snippets/javascript-remove-object-property.md
new file mode 100644
index 000000000..4320ca075
--- /dev/null
+++ b/articles/snippets/javascript-remove-object-property.md
@@ -0,0 +1,61 @@
+---
+title: How do I remove a property from a JavaScript object?
+shortTitle: Remove property from object
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: brown-bird
+excerpt: Ever wanted to delete a property from a JavaScript object? Here are a few way you can accomplish that.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+When working with objects in JavaScript, you might come across situations where a property should be completely removed from an object. To accomplish that, there a few options you have at your disposal:
+
+### Set the property to undefined
+
+Setting a property to `undefined` isn't generally optimal, as the property itself will still be present in the object, albeit `undefined`. It also mutates the original object, which might be undesired. You might want to use this in cases where you check for the property's value or truthiness but not its presence.
+
+```js
+const pet = {
+ species: 'dog',
+ age: 3,
+ name: 'celeste',
+ gender: 'female'
+};
+
+pet.gender = undefined;
+Object.keys(pet); // ['species', 'age', 'name', 'gender']
+```
+
+### Use the delete operator
+
+The `delete` operator is technically the correct way to remove a property from a JavaScript object. Unlike the previous option, `delete` will completely remove the property from the object, but it will still cause a mutation.
+
+```js
+const pet = {
+ species: 'dog',
+ age: 3,
+ name: 'celeste',
+ gender: 'female'
+};
+
+delete pet.gender;
+Object.keys(pet); // ['species', 'age', 'name']
+```
+
+### Use object destructuring
+
+Using the spread syntax, (`...`), you can destructure and assign the object with specific properties omitted to a new object. This trick comes in handy especially if you want to remove a subset of properties instead of just one and has the added benefit of not mutating the original object.
+
+```js
+const pet = {
+ species: 'dog',
+ age: 3,
+ name: 'celeste',
+ gender: 'female'
+};
+
+const { gender, ...newPet } = pet;
+Object.keys(pet); // ['species', 'age', 'name', 'gender]
+Object.keys(newPet); // ['species', 'age', 'name']
+```
diff --git a/articles/snippets/javascript-return-constructor.md b/articles/snippets/javascript-return-constructor.md
new file mode 100644
index 000000000..f6ef9b991
--- /dev/null
+++ b/articles/snippets/javascript-return-constructor.md
@@ -0,0 +1,58 @@
+---
+title: What does a JavaScript constructor return?
+shortTitle: Constructor return value
+type: question
+tags: [javascript,function,class,object]
+author: chalarangelo
+cover: architectural
+excerpt: The constructor is a crucial part of any JavaScript class, which is why you might want to take a closer look at what they return.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+The `constructor` method is a special method of a class for creating and initializing an object of that class. However, there is a little bit of magic involved around it, especially when it comes to its return value. This magic is nothing really complicated, but it seems to often confuse developers.
+
+Typically, when your constructor is invoked with `new`, an object is created, its constructor is assigned to the invoked constructor and the object is then assigned to `this` before executing any operations specified in your constructor method. Once the code is executed, the constructor will return:
+
+- Any valid `return` value, valid being only `object` values.
+- The `this` object if there is no `return` statement executed with a valid value.
+
+Let's look at some examples to better understand what's going on:
+
+```js
+class SimpleClass {
+ constructor() {
+ this.val = 0;
+ }
+}
+new SimpleClass(); // { val: 0 }
+
+class MyClass {
+ constructor() {
+ this.val = 0;
+ return { a: 1, b: 2 };
+ }
+}
+new MyClass(); // { a: 1, b : 2 }
+```
+
+The first example above shows the default behavior of a constructor, returning its `this` object if nothing else is specified. And the second one shows how a constructor can return an object different from `this`, using `return`. Note here that the use-case for such a constructor is usually a class which is implemented as a singleton or manages the number of its instances or similar.
+
+```js
+class VerboseClass {
+ constructor() {
+ this.val = 0;
+ return this;
+ }
+}
+new VerboseClass(); // { val: 0 }
+
+class PrimClass {
+ constructor() {
+ this.val = 0;
+ return 20;
+ }
+}
+new PrimitiveClass(); // { val: 0 }
+```
+
+The two examples above are not optimal, each for a different reason. The first one is too verbose, as the `this` object is returned implicitly by the constructor anyways, so there is no reason to explicitly write `return this`. On the other hand, the second example doesn't return the `return` statement's value, as it isn't an `object`, therefore resulting in the constructor returning the `this` object instead. This might lead to a lot of confusion, so you should definitely avoid it.
diff --git a/articles/snippets/javascript-shallow-deep-clone.md b/articles/snippets/javascript-shallow-deep-clone.md
new file mode 100644
index 000000000..5d0224b6e
--- /dev/null
+++ b/articles/snippets/javascript-shallow-deep-clone.md
@@ -0,0 +1,51 @@
+---
+title: How do I clone an object in JavaScript?
+shortTitle: Object cloning
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: pagodas
+excerpt: Learn how JavaScript handles mutable data, such as objects and arrays, and understand how shallow cloning and deep cloning work.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript's primitive data types, such as numbers, strings, null, undefined and booleans are immutable, meaning their value cannot change once created. However, **objects and arrays are mutable**, allowing their value to be altered after creation. What this means in practice is that primitives are passed by value, whereas objects and arrays are **passed by reference**. Consider the following example:
+
+```js
+let str = 'Hello';
+let copy = str;
+copy = 'Hi';
+// str = 'Hello', copy = 'Hi'
+
+let obj = { a: 1, b: 2 };
+let objCopy = obj;
+objCopy.b = 4;
+// obj = { a: 1, b: 4}, objCopy = { a: 1, b: 4 }
+```
+
+What happens in the of `obj` is that the object is passed by reference to `objCopy`, therefore changing the value of one of the variables also affects the other one. `objCopy` is effectively an alias referencing the same object. We can remedy this issue by cloning the object, using a variety of techniques such as the spread operator (`...`) or `Object.assign()` with an empty object:
+
+```js
+let obj = { a: 1, b: 2};
+let clone = { ...obj };
+clone.b = 4;
+// obj = { a: 1, b: 2}, clone = { a: 1, b: 4 }
+
+let otherClone = Object.assign({}, obj);
+otherClone.b = 6;
+clone.b = 4;
+// obj = { a: 1, b: 2}, otherClone = { a: 1, b: 6 }
+```
+
+Both of these solutions showcase an example of **shallow cloning**, as they will work for the outer (shallow) object, but fail if we have nested (deep) objects which will ultimately be passed by reference. As usual, there are a few approaches to this problem, the simpler of which is using `JSON.stringify()` and `JSON.parse()` to deal with the situation:
+
+```js
+let obj = { a: 1, b: { c: 2 } };
+let clone = JSON.parse(JSON.stringify(obj));
+clone.b.c = 4;
+// obj = { a: 1, b: { c: 2 }}, clone = { a: 1, b: { c: 4 } }
+```
+
+While the above example works, it has to serialize and deserialize the whole object, which can significantly impact the performance of your code, so it might not be appropriate for larger objects or in projects where performance is important.
+
+Alternatively, you can use a recursive function that deep clones an object and is a lot faster, such as the one in the [deepClone snippet](/js/s/deep-clone). Similarly, if you want a ready-to-use shallow cloning function, you can find one in the [shallowClone snippet](/js/s/shallow-clone).
diff --git a/articles/snippets/javascript-singleton-proxy.md b/articles/snippets/javascript-singleton-proxy.md
new file mode 100644
index 000000000..814e0cf1a
--- /dev/null
+++ b/articles/snippets/javascript-singleton-proxy.md
@@ -0,0 +1,54 @@
+---
+title: How can I implement a singleton in JavaScript?
+shortTitle: Singleton implementation
+type: question
+tags: [javascript,object,proxy,pattern]
+author: chalarangelo
+cover: obelisk
+excerpt: Learn how to implement the singleton design pattern in JavaScript, using the Proxy object.
+dateModified: 2021-09-28T20:11:55+03:00
+---
+
+A singleton is an **object-oriented software design pattern** which ensures a given class is only ever instantiated once. It can be useful in many different situations, such as creating global objects shared across an application. While JavaScript supports object-oriented programming, it doesn't provide many simple options to implement this pattern.
+
+The most flexible, albeit somewhat advanced, approach involves using the [Proxy object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy). The Proxy object is used to define so-called traps. Traps are methods that allow the definition of custom behavior for certain operations such as property lookup, assignment etc. The singleton pattern dictates that the given class can only have one instance. This means that the most useful trap is `handler.construct()`, the trap for the `new` operator.
+
+Turns out the `handler` is itself just an object. Apart from `handler.constructor()`, we can use the handler to store the unique instance of the class we want and if it has been instantiated. In doing so, we can create a handler object that can be reused for any class we want to convert into a singleton, while also allowing us to provide additional traps for any other operations we might want to customize.
+
+Here's the most basic version of a function that takes a `class` and converts it into a singleton, based on the above explanation:
+
+```js
+const singletonify = (className) => {
+ return new Proxy(className.prototype.constructor, {
+ instance: null,
+ construct: (target, argumentsList) => {
+ if (!this.instance)
+ this.instance = new target(...argumentsList);
+ return this.instance;
+ }
+ });
+}
+```
+
+And here is a simple practical example to better understand what it does:
+
+```js
+class MyClass {
+ constructor(msg) {
+ this.msg = msg;
+ }
+
+ printMsg() {
+ console.log(this.msg);
+ }
+}
+
+MySingletonClass = singletonify(MyClass);
+
+const myObj = new MySingletonClass('first');
+myObj.printMsg(); // 'first'
+const myObj2 = new MySingletonClass('second');
+myObj2.printMsg(); // 'first'
+```
+
+In the above example, you can see that the second time `MySingletonClass` is instantiated, nothing happens. This is due to the fact that an instance already exists, so it is returned instead of a new object being created. As mentioned, this is a bare-bones implementation of a `singletonify` function. It can be extended to modify the behavior further or use some of the data passed to the constructor in later calls to update the `instance` it holds.
diff --git a/articles/snippets/javascript-sleep.md b/articles/snippets/javascript-sleep.md
new file mode 100644
index 000000000..6f449d775
--- /dev/null
+++ b/articles/snippets/javascript-sleep.md
@@ -0,0 +1,64 @@
+---
+title: How can I implement a sleep function in JavaScript?
+shortTitle: Sleep function
+type: question
+tags: [javascript,date,promise]
+author: chalarangelo
+cover: sleepy-cat
+excerpt: Learn all the different ways you can implement a `sleep()` function in JavaScript.
+dateModified: 2021-11-06T20:51:47+03:00
+---
+
+JavaScript does not come with a `sleep()` function out of the box. That's probably a good idea considering the environments where it runs and the trouble it could cause if used incorrectly. The closest equivalent is the `setTimeout()` function, but there are other, less common ways to implement a function that will pause execution for a specified amount of time.
+
+### setTimeout
+
+JavaScript's `setTimeout()` sets a timer which executes some code once the timer expires. Only the code inside the `setTimeout()` callback will execute after the timer expires. This can lead to nesting issues, as well as code executing out of order if you are not careful.
+
+```js
+const printNums = () => {
+ console.log(1);
+ setTimeout(() => console.log(2), 500);
+ console.log(3);
+};
+
+printNums(); // Logs: 1, 3, 2 (2 logs after 500ms)
+```
+
+### Synchronous version
+
+While strongly discouraged, `Date.prototype.getTime()` can be used inside a `while` loop to pause execution for a set amount of time. You can easily define a synchronous `sleep()` function like this:
+
+```js
+const sleepSync = (ms) => {
+ const end = new Date().getTime() + ms;
+ while (new Date().getTime() < end) { /* do nothing */ }
+}
+
+const printNums = () => {
+ console.log(1);
+ sleepSync(500);
+ console.log(2);
+ console.log(3);
+};
+
+printNums(); // Logs: 1, 2, 3 (2 and 3 log after 500ms)
+```
+
+### Asynchronous version
+
+A less intrusive way to go about implementing a `sleep()` function is to utilize the `async` and `await` keywords added in JavaScript ES6, a `Promise` and `setTimeout()`. Note that the resulting function must be executed in an `async` function and has to be called with `await`:
+
+```js
+const sleep = (ms) =>
+ new Promise(resolve => setTimeout(resolve, ms));
+
+const printNums = async() => {
+ console.log(1);
+ await sleep(500);
+ console.log(2);
+ console.log(3);
+};
+
+printNums(); // Logs: 1, 2, 3 (2 and 3 log after 500ms)
+```
diff --git a/articles/snippets/javascript-spread-rest-syntax.md b/articles/snippets/javascript-spread-rest-syntax.md
new file mode 100644
index 000000000..9f9730d7d
--- /dev/null
+++ b/articles/snippets/javascript-spread-rest-syntax.md
@@ -0,0 +1,54 @@
+---
+title: Understanding the spread and rest syntax in Javascript
+shortTitle: Spread and rest syntax
+type: story
+tags: [javascript,array,function]
+author: chalarangelo
+cover: antelope
+excerpt: JavaScript ES6 introduced us to powerful new features, such as the spread and rest syntax. Learn all you need to know in this quick guide.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### Spread syntax
+
+The spread operator (`...`) allows you to expand a single array into its values. Some common use-cases for the spread operator include:
+
+- Expanding an array's values to pass them as arguments to a function that does not accept an array.
+- Cloning an array by spreading its values into a new array (`[]`).
+- Concatenating arrays by spreading them into a new array (`[]`).
+- Flattening an array of arrays one level, by spreading nested arrays.
+- Converting a non-array iterable (e.g. a string or a `Set`) to an array.
+
+```js
+// Array's values as arguments
+const a = [1, 2, 3];
+Math.max(...a); // 3
+
+// Clone an array
+const b = [4, 5, 6];
+const c = [...b]; // c = [4, 5, 6], b !== c
+
+// Concatenate two arrays
+const d = [...a, ...b]; // d = [1, 2, 3, 4, 5, 6]
+
+// Flatten an array
+const e = [[1, 2], [3, 4]];
+const f = [...e[0], ...e[1]]; // f = [1, 2, 3, 4]
+
+// Convert iterable to array
+const g = [...'hello']; // g = ['h', 'e', 'l', 'l', 'o']
+```
+
+### Rest syntax
+
+The rest parameter syntax allows you to collapse any remaining arguments into an array. While it looks very similar to the spread operator, the rest parameter syntax is only used in function declarations (arrow or otherwise).
+
+```js
+// Rest parameter syntax, not to be confused with the spread operator
+const fn = (str, ...nums) => `${str}_${nums.join('')}`;
+fn('hi', 1, 2, 3); // 'hi_123', `nums` will be [1, 2, 3]
+
+const data = [4, 5, 6];
+// Spread operator, expanding the array
+fn('hey', ...data); // 'hey_456', `nums` will be [4, 5, 6]
+```
diff --git a/articles/snippets/javascript-store-dom-items.md b/articles/snippets/javascript-store-dom-items.md
new file mode 100644
index 000000000..c8489f82b
--- /dev/null
+++ b/articles/snippets/javascript-store-dom-items.md
@@ -0,0 +1,27 @@
+---
+title: "Tip: Minimize DOM access"
+shortTitle: Minimize DOM access
+type: tip
+tags: [javascript,browser]
+author: chalarangelo
+cover: armchair
+excerpt: Increase your JavaScript code's performance when working with the DOM by leveraging this simple trick.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+DOM operations, including accessing the DOM, are generally slow. This is usually not a problem until you have to perform many DOM operations and your JavaScript application's performance starts to suffer. A very quick trick to increase performance is to store DOM elements or their values in local variables if you plan to access them multiple times.
+
+```js
+// This is slow, it accesses the DOM element multiple times
+document.querySelector('#my-element').classList.add('my-class');
+document.querySelector('#my-element').textContent = 'hello';
+document.querySelector('#my-element').hidden = false;
+
+// This is faster, it stores the DOM element in a variable
+const myElement = document.querySelector('#my-element');
+myElement.classList.add('my-class');
+myElement.textContent = 'hello';
+myElement.hidden = false;
+```
+
+Note that, while this trick may come in handy, it comes with the caveat that if you later remove the DOM element and you still have it stored in a variable, the variable should be set to `null` to avoid potential memory leaks.
diff --git a/articles/snippets/javascript-string-contains-substring.md b/articles/snippets/javascript-string-contains-substring.md
new file mode 100644
index 000000000..a915e6e9f
--- /dev/null
+++ b/articles/snippets/javascript-string-contains-substring.md
@@ -0,0 +1,40 @@
+---
+title: Check if a string contains a substring in JavaScript
+shortTitle: String contains substring
+type: story
+tags: [javascript,string]
+author: chalarangelo
+cover: sea-view-2
+excerpt: Let's have a look at how to check if a string contains a substring in JavaScript.
+dateModified: 2022-07-27T05:00:00-04:00
+---
+
+### String.prototype.includes()
+
+The most straightforward substring search option is `String.prototype.includes()`, introduced in ES6. It's a simple method that returns a boolean value depending on whether the string contains the substring or not.
+
+```js
+const str = 'Hello world';
+str.includes('world'); // true
+str.includes('foo'); // false
+```
+
+### String.prototype.indexOf()
+
+Another option is `String.prototype.indexOf()`, which can be preferable if you need to support legacy browsers. As this methods returns the index of the first occurrence of the substring, you need to compare it to `-1` to know if the substring was found or not.
+
+```js
+const str = 'Hello world';
+str.indexOf('world') !== -1; // true
+str.indexOf('foo') !== -1; // false
+```
+
+### Case-insensitive substring search
+
+Both methods presented so far are case-sensitive. If you need to search for a substring that is case-insensitive, you can use `String.prototype.toLowerCase()` to convert both strings to lowercase. Then you can compare them, using any of the previous methods.
+
+```js
+const str = 'Hello world';
+const token = 'WORLD';
+str.toLowerCase().includes(token.toLowerCase()); // true
+```
diff --git a/articles/snippets/javascript-string-immutability.md b/articles/snippets/javascript-string-immutability.md
new file mode 100644
index 000000000..c533fa18b
--- /dev/null
+++ b/articles/snippets/javascript-string-immutability.md
@@ -0,0 +1,20 @@
+---
+title: Are JavaScript strings immutable?
+shortTitle: String immutability
+type: question
+tags: [javascript,string,type]
+author: chalarangelo
+cover: purple-sunset
+excerpt: When it comes to immutability, JavaScript strings are often a source of confusion. Yet they're not as complicated as you might expect.
+dateModified: 2021-10-10T05:00:00-04:00
+---
+
+String specifications among programming languages vary, however most languages treat them as reference types. But strings in JavaScript are different. They are **immutable primitives**. This means that the characters within them may not be changed and that any operations on strings actually create new strings.
+
+```js
+const x = 'type';
+x[1] = 'a'; // Nothing happens, doesn't throw an error
+console.log(x); // LOGS: 'type'
+```
+
+It helps to think of strings in the way that we think of numbers, if we are to better understand how they work. Numeric values are also immutable primitives. If, for example, you could mutate numbers, you could change the meaning of the value `42` to be another number, say `13`. In the same sense, you cannot mutate a string with a value of `gem` to make it `gym`.
diff --git a/articles/snippets/javascript-string-to-boolean.md b/articles/snippets/javascript-string-to-boolean.md
new file mode 100644
index 000000000..9d47ad7a1
--- /dev/null
+++ b/articles/snippets/javascript-string-to-boolean.md
@@ -0,0 +1,34 @@
+---
+title: "Tip: Convert a string to a boolean"
+shortTitle: String to boolean
+type: tip
+tags: [javascript,string,boolean,type]
+author: chalarangelo
+cover: two-cities
+excerpt: Have you ever tried to convert the string representation of a boolean to an actual boolean value? Here's a simple way to do it.
+dateModified: 2022-09-14T05:00:00-04:00
+---
+
+Sometimes, one might run into the problem of converting the string representation of a value into the value itself. This is often straightforward, such as with numeric values. However, string representations of boolean values can be a bit trickier.
+
+This issue arises due to the fact that any non-empty string is considered truthy in JavaScript. On top of that, strings can have different capitalization or whitespace, making it harder to compare them directly to a constant.
+
+To counteract this, it's often a good idea to use a couple of transformations, namely `String.prototype.toLowerCase()` and `String.prototype.trim()`, to make the string representation of the value more consistent. Additionally, an array of acceptable values might make it easier to perform the conversion in certain cases.
+
+```js
+const toBoolean = (value, truthyValues = ['true']) => {
+ const normalizedValue = String(value).toLowerCase().trim();
+ return truthyValues.includes(normalizedValue);
+};
+
+toBoolean('true'); // true
+toBoolean('TRUE'); // true
+toBoolean('True'); // true
+toBoolean('tRue '); // true
+toBoolean('false'); // false
+toBoolean('FALSE'); // false
+toBoolean('False'); // false
+toBoolean('fAlse '); // false
+toBoolean('YES', ['yes']); // true
+toBoolean('no', ['yes']); // false
+```
diff --git a/articles/snippets/javascript-swap-two-variables.md b/articles/snippets/javascript-swap-two-variables.md
new file mode 100644
index 000000000..5d5188f32
--- /dev/null
+++ b/articles/snippets/javascript-swap-two-variables.md
@@ -0,0 +1,37 @@
+---
+title: "Tip: How to swap two variables in JavaScript"
+shortTitle: Swap two variables
+type: tip
+tags: [javascript,variables]
+author: chalarangelo
+cover: mountain-lake-2
+excerpt: Learn how to swap the values of two variables in JavaScript using a single line of ES6 code.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+In the past, swapping the values of two variables in JavaScript required an intermediate variable to store one of the values while swapping, which would result in something similar to this:
+
+```js
+let a = 10;
+let b = 20;
+
+let tmp;
+tmp = a;
+a = b;
+b = tmp;
+```
+
+While this approach still works, there are more elegant and less verbose options available to us nowadays. For example, JavaScript ES6 introduced **destructuring assignments**, allowing individual array items to be assigned to variables in a single statement. Here's what that looks like:
+
+```js
+const [x, y] = [1, 2];
+```
+
+Destructuring assignments are extremely useful in a handful of situations, including swapping two variables. To accomplish this, we can create an array from the two variables, then use a destructuring assignment to reassign them to each other:
+
+```js
+let a = 10;
+let b = 20;
+
+[a , b] = [b, a];
+```
diff --git a/articles/snippets/javascript-switch-object.md b/articles/snippets/javascript-switch-object.md
new file mode 100644
index 000000000..e6113818e
--- /dev/null
+++ b/articles/snippets/javascript-switch-object.md
@@ -0,0 +1,109 @@
+---
+title: Replacing JavaScript switch statement with object literals
+shortTitle: Switch with object literals
+type: story
+tags: [javascript,object]
+author: chalarangelo
+cover: rocky-lake
+excerpt: JavaScript's `switch` statement often feels hard to remember and a little bit out of place. Maybe it's time to use object literals, instead.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+JavaScript's `switch` statement is one of the few things I find hard to remember the syntax for (so glad VS Code has autocomplete). It also feels a little bit out of place syntactically, as it's the only thing that doesn't use curly braces and you need to remember to `break` for every `case`. Moreover, its performance is less than stellar as its control flow is procedural.
+
+Luckily, JavaScript's object literals are a pretty good alternative for most `switch` statement use-cases I can think of. The idea is to define an object with a key for each `case` you would have in a `switch` statement. Then you can access its value directly using the expression you would pass to the `switch` statement.
+
+```js
+let fruit = 'oranges';
+
+switch (fruit) {
+ case 'apples':
+ console.log('Apples');
+ break;
+ case 'oranges':
+ console.log('Oranges');
+ break;
+}
+// Logs: 'Oranges'
+
+const logFruit = {
+ 'apples': () => console.log('Apples'),
+ 'oranges': () => console.log('Oranges')
+};
+
+logFruit[fruit](); // Logs: 'Oranges'
+```
+
+While this is infinitely more readable and less verbose, it's also significantly faster. However, we haven't yet addressed the elephant in the room: the `default` case. To handle it, we can just add a `'default'` key and check if the expression's value exists in our object.
+
+```js
+let fruit = 'strawberries';
+
+switch (fruit) {
+ case 'apples':
+ console.log('Apples');
+ break;
+ case 'oranges':
+ console.log('Oranges');
+ break;
+ default:
+ console.log('Unknown fruit');
+}
+// Logs: 'Unknown fruit'
+
+const logFruit = {
+ 'apples': () => console.log('Apples'),
+ 'oranges': () => console.log('Oranges'),
+ 'default': () => console.log('Unknown fruit')
+};
+
+(logFruit[fruit] || logFruit['default'])(); // Logs: 'Unknown fruit'
+```
+
+Finally, our object literal replacement should be able to handle falling through cases, similar to what happens when there's no `break` statement. This is a matter of simply extracting and reusing logic in the object literal.
+
+```js
+let fruit = 'oranges';
+
+switch (fruit) {
+ case 'apples':
+ case 'oranges':
+ console.log('Known fruit');
+ break;
+ default:
+ console.log('Unknown fruit');
+}
+// Logs: 'Known fruit'
+
+const knownFruit = () => console.log('Known fruit');
+const unknownFruit = () => console.log('Unknown fruit');
+
+const logFruit = {
+ 'apples': knownFruit,
+ 'oranges': knownFruit,
+ 'default': unknownFruit
+};
+
+(logFruit[fruit] || logFruit['default'])(); // Logs: 'Known fruit'
+```
+
+To wrap this all up, we can generalize and extract this logic into a simple reusable function. We will supply it with the lookup object and an optional name for the default case (we'll default to `_default` to avoid any conflicts). This function will in turn return a function with the appropriate lookup logic and we can use it to replace any `switch` statement.
+
+```js
+const switchFn = (lookupObject, defaultCase = '_default') =>
+ expression => (lookupObject[expression] || lookupObject[defaultCase])();
+
+const knownFruit = () => console.log('Known fruit');
+const unknownFruit = () => console.log('Unknown fruit');
+
+const logFruit = {
+ 'apples': knownFruit,
+ 'oranges': knownFruit,
+ 'default': unknownFruit
+};
+
+const fruitSwitch = switchFn(logFruit, 'default');
+
+fruitSwitch('apples'); // Logs: 'Known fruit'
+fruitSwitch('pineapples'); // Logs: 'Unknown fruit'
+```
diff --git a/articles/snippets/javascript-sync-async.md b/articles/snippets/javascript-sync-async.md
new file mode 100644
index 000000000..0d245bd20
--- /dev/null
+++ b/articles/snippets/javascript-sync-async.md
@@ -0,0 +1,30 @@
+---
+title: What is the difference between synchronous and asynchronous code in JavaScript?
+shortTitle: Synchronous vs asynchronous code
+type: question
+tags: [javascript,function,promise]
+author: chalarangelo
+cover: pineapple-on-green
+excerpt: Understanding the differences between synchronous and asynchronous code is a crucial piece of knowledge for every web developer.
+dateModified: 2021-11-14T05:00:00-04:00
+---
+
+Synchronous code runs in sequence. This means that each operation must wait for the previous one to complete before executing.
+
+```js
+console.log('One');
+console.log('Two');
+console.log('Three');
+// LOGS: 'One', 'Two', 'Three'
+```
+
+Asynchronous code runs in parallel. This means that an operation can occur while another one is still being processed.
+
+```js
+console.log('One');
+setTimeout(() => console.log('Two'), 100);
+console.log('Three');
+// LOGS: 'One', 'Three', 'Two'
+```
+
+Asynchronous code execution is often preferable in situations where execution can be blocked indefinitely. Some examples of this are network requests, long-running calculations, file system operations etc. Using asynchronous code in the browser ensures the page remains responsive and the user experience is mostly unaffected.
diff --git a/articles/snippets/javascript-target-blank.md b/articles/snippets/javascript-target-blank.md
new file mode 100644
index 000000000..1d55164df
--- /dev/null
+++ b/articles/snippets/javascript-target-blank.md
@@ -0,0 +1,32 @@
+---
+title: 'Tip: Protect your users from malicious websites when using target="_blank"'
+shortTitle: 'Safeguarding target="_blank"'
+type: tip
+tags: [javascript,browser,security]
+author: chalarangelo
+cover: laptop-with-code
+excerpt: Opening a link in a new tab comes with a security vulnerability that you may not be aware of. Protect your users with this simple trick.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Oftentimes, when linking to an external resource from our websites, we use `target="_blank"` to open the linked page in a new tab or window. But there is a security risk we should be aware of. The new tab gains limited access to the linking page (i.e. our website) via `Window.opener`, which it can then use to alter the linking page's URL via `Window.opener.location` (this is known as tabnabbing).
+
+This might be a problem if the external resource is not trustworthy, might have been hacked, the domain has changed owners over the years etc. There is no guarantee that a third-party resource, no matter how trustworthy, can be actually trusted with our users' security and we, as developers, should always be aware of this risk.
+
+```html
+
+
+ External resource
+
+
+
+
+ External resource
+
+```
+
+In order to prevent a link that is opened in a new tab from causing any trouble, we should always add the `rel="noopener noreferrer"` attribute to all of our `target="_blank"` links.
diff --git a/articles/snippets/javascript-ternary-operator.md b/articles/snippets/javascript-ternary-operator.md
new file mode 100644
index 000000000..cafa33a89
--- /dev/null
+++ b/articles/snippets/javascript-ternary-operator.md
@@ -0,0 +1,47 @@
+---
+title: What is the ternary operator and how do I use it?
+shortTitle: Ternary operation introduction
+type: question
+tags: [javascript,condition]
+cover: red-succulent
+excerpt: Learn everything you need to know about the conditional (ternary) operator and how to use it in JavaScript.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+JavaScript's ternary operator (`?:`), also called the conditional operator, is used to replace a conditional statement, most commonly an assignment. For example:
+
+```js
+// Code using if...else
+let x;
+if (someCondition) {
+ x = 10;
+} else {
+ x = 20;
+}
+
+// Same result using the ternary operator
+const x = someCondition ? 10 : 20;
+```
+
+As you can tell from the above example, the ternary operator is shorter than using an `if...else` statement and allows us to assign the resulting value to a variable, provided the condition is pretty much a one-liner. A useful result of this is that we can use the ternary operator for arrow functions with implicit returns:
+
+```js
+// Code using if...else
+const conditionalX = (condition, x) => {
+ if (condition) return x;
+ else return x + 5;
+}
+
+// Same result using the ternary operator
+const conditionalX = (condition, x) => condition ? x : x + 5;
+```
+
+Note, however, that nesting ternary expressions is usually discouraged with ESLint even going as far as having a [dedicated rule](https://eslint.org/docs/rules/no-nested-ternary) for this kind of situation. Additionally, the ternary operator is a favorite of React developers, as it allows for easy conditional rendering in JSX code:
+
+```jsx
+const ItemListTitle = (count) => (
+ Item list{ count ? ( - {count} items ) : '(Empty)'}
+);
+```
+
+Finally, you might be wondering why it's called the "ternary" operator. The word "ternary" is based on the [n-ary word setup](https://en.wikipedia.org/wiki/Arity) and means an operator with three operands (condition, expression to execute if truthy, expression to execute if falsy).
diff --git a/articles/snippets/javascript-this.md b/articles/snippets/javascript-this.md
new file mode 100644
index 000000000..22d533841
--- /dev/null
+++ b/articles/snippets/javascript-this.md
@@ -0,0 +1,142 @@
+---
+title: Understanding the "this" keyword in JavaScript
+shortTitle: The "this" keyword in JavaScript
+type: story
+tags: [javascript,function,object]
+author: chalarangelo
+cover: u-got-this
+excerpt: JavaScript's `this` keyword can confuse beginners and veterans alike. Learn how it works in different scenarios and start using it correctly.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### What is `this`?
+
+In JavaScript, the `this` keyword refers to the object that is currently executing the code. The short version of what `this` evaluates to is as follows:
+
+- By default, `this` refers to the global object.
+- In a function, when not in strict mode, `this` refers to the global object.
+- In a function, when in strict mode, `this` is `undefined`.
+- In an arrow function, `this` retains the value of the enclosing lexical context's `this`.
+- In an object method, `this` refers to the object the method was called on.
+- In a constructor call, `this` is bound to the new object being constructed.
+- In an event handler, `this` is bound to the element on which the listener is placed.
+
+### Global context
+
+In the global execution context, `this` refers to the global object.
+
+```js
+console.log(this === window); // true
+```
+
+### Function context
+
+When not in strict mode, a function's `this` refers to the global object.
+
+```js
+function f() {
+ return this;
+}
+
+console.log(f() === window); // true
+```
+
+When in strict mode, a function's `this` will be `undefined` if not set when entering the execution context.
+
+```js
+'use strict';
+
+function f() {
+ return this;
+}
+
+console.log(f()); // undefined
+```
+
+### Object context
+
+When a function is called as a method of an object, `this` refers to the object the method is called on. This applies to methods defined anywhere in the object's prototype chain (i.e. own and inherited methods).
+
+```js
+const obj = {
+ f: function() {
+ return this;
+ }
+};
+
+const myObj = Object.create(obj);
+myObj.foo = 1;
+
+console.log(myObj.f()); // { foo: 1 }
+```
+
+Similarly, when used inside a constructor, `this` refers to the object being constructed.
+
+```js
+class C {
+ constructor() {
+ this.x = 10;
+ }
+}
+
+const obj = new C();
+console.log(obj.x); // 10
+```
+
+### Arrow function context
+
+In arrow functions, `this` retains the value of the enclosing lexical context's `this`.
+
+```js
+const f = () => this;
+
+console.log(f() === window); // true
+
+const obj = {
+ foo: function() {
+ const baz = () => this;
+ return baz();
+ },
+ bar: () => this
+};
+
+console.log(obj.foo()); // { foo, bar }
+console.log(obj.bar() === window); // true
+```
+
+Notice how in the second example, an arrow function's `this` refers to the global object unless wrapped inside a regular `function` call, whose `this` refers to the object it's called from and its lexical context is retained by the arrow function.
+
+### Event handler context
+
+When used in an event handler, `this` refers to the element on which the listener is placed.
+
+```js
+const el = document.getElementById('my-el');
+
+el.addEventListener('click', function() {
+ console.log(this === el); // true
+});
+```
+
+### Binding `this`
+
+Using `Function.prototype.bind()` returns a new function from an existing one, where `this` is permanently bound to the first argument of `bind()`.
+
+```js
+function f() {
+ return this.foo;
+}
+
+var x = f.bind({foo: 'hello'});
+console.log(x()); // 'hello'
+```
+
+Similarly, using `Function.prototype.call()` or `Function.prototype.apply()` will bind the called function's `this` to the first argument of either of these functions only for this call.
+
+```js
+function f() {
+ return this.foo;
+}
+
+console.log(f.call({foo: 'hi'})); // 'hi'
+```
diff --git a/articles/snippets/javascript-truthy-falsy-values.md b/articles/snippets/javascript-truthy-falsy-values.md
new file mode 100644
index 000000000..9787954f3
--- /dev/null
+++ b/articles/snippets/javascript-truthy-falsy-values.md
@@ -0,0 +1,45 @@
+---
+title: What are truthy and falsy values in JavaScript?
+shortTitle: Truthy and falsy values
+type: question
+tags: [javascript,type,comparison]
+author: chalarangelo
+cover: little-bird
+excerpt: JavaScript uses type coercion in Boolean contexts, resulting in truthy or falsy values. Get a hang of how it all works in this quick guide.
+dateModified: 2021-09-12T05:00:00-04:00
+---
+
+JavaScript uses **type coercion** (implicit conversion of values from one data type to another) in Boolean contexts, such as conditionals. This means that values are considered either truthy (evaluate to `true`) or falsy (evaluate to `false`) depending on how they are evaluated in a Boolean context.
+
+There are 6 values that are considered **falsy** in JavaScript:
+
+- The keyword `false`
+- The primitive value `undefined`
+- The primitive value `null`
+- The empty string (`''`, `""`)
+- The global property `NaN`
+- A number or BigInt representing `0` (`0`, `-0`, `0.0`, `-0.0`, `0n`)
+
+Every other value is considered **truthy**. It's important to remember that this applies to all JavaScript values, even ones that might seem falsy, such as empty arrays (`[]`) or empty objects (`{}`).
+
+You can check a value's truthiness using either the `Boolean()` function or a double negation (`!!`).
+
+```js
+Boolean(false); // false
+Boolean(undefined); // false
+Boolean(null); // false
+Boolean(''); // false
+Boolean(NaN); // false
+Boolean(0); // false
+Boolean(-0); // false
+Boolean(0n); // false
+
+Boolean(true); // true
+Boolean('hi'); // true
+Boolean(1); // true
+Boolean([]); // true
+Boolean([0]); // true
+Boolean([1]); // true
+Boolean({}); // true
+Boolean({ a: 1 }); // true
+```
diff --git a/articles/snippets/javascript-undeclared-undefined-null.md b/articles/snippets/javascript-undeclared-undefined-null.md
new file mode 100644
index 000000000..dbc3021a4
--- /dev/null
+++ b/articles/snippets/javascript-undeclared-undefined-null.md
@@ -0,0 +1,40 @@
+---
+title: What's the difference between undeclared, undefined and null in JavaScript?
+shortTitle: Undeclared, undefined and null
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: river-houses
+excerpt: JavaScript has three different empty states for variables. Learn their differences and how you can check for each one.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+### undeclared
+
+A variable is undeclared if it has not been declared with an appropriate keyword (i.e. `var`, `let` or `const`). Accessing an undeclared variable will throw a `ReferenceError`.
+
+```js
+console.log(x); // ReferenceError: x is not defined
+```
+
+### undefined
+
+A variable is `undefined` if it hasn't been assigned a value. `undefined` is a primitive data type in JavaScript and represents the absence of a value, intentional or otherwise.
+
+```js
+let x;
+console.log(x); // undefined
+```
+
+### null
+
+A variable is assigned a value of `null` like any other value. `null` is also primitive data type in JavaScript and always represents the intentional absence of a value.
+
+```js
+let x = null;
+console.log(x); // null
+```
+
+### Checking for empty states
+
+Undeclared variables will throw an error, which makes them easy to spot and are not very common anyways. `undefined` and `null` can be easily spotted with a conditional as they are both falsy values. Due to that, `null` and `undefined` are loosely equal (`==`), but not strictly equal (`===`).
diff --git a/articles/snippets/javascript-use-strict.md b/articles/snippets/javascript-use-strict.md
new file mode 100644
index 000000000..8d252f112
--- /dev/null
+++ b/articles/snippets/javascript-use-strict.md
@@ -0,0 +1,114 @@
+---
+title: What does 'use strict' do and what are some of the key benefits to using it?
+shortTitle: Strict mode introduction
+type: question
+tags: [javascript,function,object]
+author: chalarangelo
+cover: palm-tree-house
+excerpt: JavaScript's strict mode can make your code faster, cleaner and more secure.
+dateModified: 2021-11-28T05:00:00-04:00
+---
+
+Strict mode can be applied to entire scripts or individual functions by including `'use strict'` before any other statements.
+
+```js
+// script.js
+'use strict';
+const x = "Hello from a strict mode script";
+
+// other.js
+function strict() {
+ 'use strict';
+ const x = 'Hello from a strict mode function';
+}
+```
+
+This enforces more strict parsing and error handling of JavaScript code, as described below.
+
+### No accidental global variables
+
+Strict mode makes it impossible to accidentally create global variables due to mistyped variable names. Assignments, which would accidentally create global variables, instead throw an error in strict mode:
+
+```js
+'use strict';
+myVariable = 42;
+// The above line will throw a ReferenceError, assuming no global
+// variable named myVariable has been declared previously
+```
+
+### Elimination of silent errors
+
+Strict mode changes some previously-accepted mistakes into errors. These include:
+
+- Assignments which would otherwise silently fail
+- Deleting undeletable properties or plain names
+- Duplicated names in function arguments
+- 0-prefixed octal literals
+- Setting properties on primitives
+
+```js
+'use strict';
+
+let undefined = 5; // TypeError (non-writable global)
+let obj = {};
+Object.defineProperty(obj1, 'x', { value: 1, writable: false });
+obj.x = 2; // TypeError (non-writable property);
+
+delete Object.prototype; // TypeError (undeletable property)
+delete something; // SyntaxError (plain name)
+
+const sum (a, b, b) { // SyntaxError (duplicated argument name)
+ return a + b + b;
+}
+
+const x = 012; // SyntaxError (0-prefixed octal literal)
+
+false.true = 10; // TypeError (property on primitive)
+```
+
+### Simplified `eval`
+
+Strict mode makes `eval` more transparent by preventing the introduction of new variables in the surrounding scope. In strict mode, `eval` creates variables only for the code being evaluated.
+
+```js
+'use strict';
+let x = 1;
+eval('let x = 3; console.log(x);'); // LOGS: 3
+console.log(x); // LOGS: 1
+```
+
+### Simplified `arguments`
+
+Strict mode simplifies `arguments`, by removing some of their side effects. `arguments` aren't aliased, thus they always refer to the original arguments when the function was invoked. Moreover, `arguments.callee` and `arguments.caller` are no longer supported.
+
+```js
+'use strict';
+function f(x) {
+ x = 5;
+ return x === arguments[0];
+}
+
+f(10); // false
+```
+
+### No `this` boxing
+
+Strict mode makes JavaScript more secure, by restricting access the global object via `this`. In strict mode, `this` is not boxed (forced into being an object), meaning that if unspecified it will be `undefined` instead of the global object.
+
+```js
+'use strict';
+function f() {
+ return this;
+}
+
+f(); // undefined
+```
+
+### Other changes
+
+Strict mode implements a few more, less commonly-mentioned changes. These include:
+
+- `with` is prohibited, resulting in an error if used
+- `Function.prototype.arguments` and `Function.prototype.caller` are non-deletable properties which throw when set or retrieved
+- `implements`, `interface`, `let`, `package`, `private`, `protected`, `public`, `static`, and `yield` are reserved keywords
+- Function statements are only allowed at the top level of a script of function
diff --git a/articles/snippets/javascript-value-as-number.md b/articles/snippets/javascript-value-as-number.md
new file mode 100644
index 000000000..46c9f4262
--- /dev/null
+++ b/articles/snippets/javascript-value-as-number.md
@@ -0,0 +1,25 @@
+---
+title: "Tip: You can get the value of an input element as a number"
+shortTitle: Input element value as number
+type: tip
+tags: [javascript,browser,input]
+author: chalarangelo
+cover: mac-and-coffee
+excerpt: Ever wanted to get the value of an HTML input element as a number? Learn an easy way to do it with this handy trick.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Most of the time, when accessing the value of an `HTMLInputElement` in an event listener, we use something along the lines of `e.target.value`. This is fine in most cases, but when we want the numeric value of an input field, we have to parse it and check if the value is actually valid etc. That can get very annoying, especially when working with larger forms that have many input fields.
+
+What if I told you there's an easier way to get the numeric value from an input field? Meet `HTMLInputElement.valueAsNumber`, a handy attribute that will return a numeric value if the input field's value can be converted to a number or `NaN` if the conversion is not possible.
+
+```js
+const quantityInput = document.getElementById('quantity-input');
+let quantity;
+// Bad: parseFloat() converts the string to a number
+quantity = parseFloat(quantityInput.value);
+// Good: returns a numeric value
+quantity = quantityInput.valueAsNumber;
+```
+
+As usual, this comes with a caveat which is that it only works for `type="number"` inputs (although that's probably where you need it the most). On a side note, you can also use `HTMLInputElement.valueAsDate` to get a `Date` object from a `type="date"` input, which might also come in handy in some cases.
diff --git a/articles/snippets/javascript-value-not-equal-to-itself.md b/articles/snippets/javascript-value-not-equal-to-itself.md
new file mode 100644
index 000000000..3285cf44b
--- /dev/null
+++ b/articles/snippets/javascript-value-not-equal-to-itself.md
@@ -0,0 +1,28 @@
+---
+title: What is the only value not equal to itself in JavaScript?
+shortTitle: The only value not equal to itself
+type: question
+tags: [javascript,type,comparison]
+author: chalarangelo
+cover: eagle
+excerpt: Did you know there's a JavaScript value that's not equal to itself?
+dateModified: 2021-12-12T05:00:00-04:00
+---
+
+`NaN` (Not-a-Number) is the only JavaScript value not equal to itself when comparing with any of the comparison operators. `NaN` is often the result of meaningless or invalid math computations, so it doesn't make sense for two `NaN` values to be considered equal.
+
+```js
+const x = Math.sqrt(-1); // NaN
+const y = 0 / 0; // NaN
+
+x === y; // false
+x === NaN; // false
+
+Number.isNaN(x); // true
+Number.isNaN(y); // true
+
+isNaN(x); // true
+isNan('hello'); // true
+```
+
+You can check for `NaN` values using the `Number.isNaN()` function. Note that this is different from the original , global `isNaN()`. Their difference lies in the fact that `isNaN()` forcefully converts its argument to a number, whereas `Number.isNaN()` doesn't. This is why `Number.isNaN()` is considered more robust and preferable in most cases.
diff --git a/articles/snippets/javascript-var-let-const.md b/articles/snippets/javascript-var-let-const.md
new file mode 100644
index 000000000..e85eacb22
--- /dev/null
+++ b/articles/snippets/javascript-var-let-const.md
@@ -0,0 +1,80 @@
+---
+title: What are the differences between var, let and const in JavaScript?
+shortTitle: Var, let and const
+type: question
+tags: [javascript,type,variable]
+author: chalarangelo
+cover: highlands
+excerpt: JavaScript variables can be declared a handful of ways. However, understanding their differences can drastically change the way you code.
+dateModified: 2021-12-02T09:50:42-04:00
+---
+
+JavaScript has three variable declaration statements: `var`, `let` and `const`. The latter two were added in ES6, whereas `var` existed since previous versions. One of the first things to notice is that `const` defines constants (i.e. values that will not be reassigned), whereas `var` and `let` define variables. Yet, `var` behaves differently from both `let` and `const` in various other ways.
+
+### Scope
+
+Variables declared with `var` are function scoped, in contrast to variables declared with `let` or `const` which are block scoped.
+
+```js
+const scopeExample = () => {
+ var a = 'var';
+ let b = 'let';
+ console.log(a, b); // 'var', 'let'
+
+ {
+ var c = 'var';
+ let d = 'let';
+ console.log(c, d); // 'var', 'let'
+ }
+
+ console.log(c); // 'var'
+ console.log(d); // Throws a ReferenceError
+};
+```
+
+If you want to learn more, we have [an article covering JavaScript variables and scopes in more depth](/articles/s/javascript-variable-scope).
+
+### Hoisting
+
+While variables declared with `var` are hoisted to the enclosing scope, variables declared with `let` or `const` are not initialized until their definition is evaluated.
+
+```js
+const hoistingExample = () => {
+ console.log(a); // undefined
+ var a = 'var';
+ console.log(a); // 'var'
+
+ console.log(b); // ReferenceError
+ let b = 'let';
+ console.log(b); // 'let'
+};
+```
+
+If you want to learn more, we have [an article covering JavaScript hoisting in more depth](/articles/s/javascript-variable-hoisting).
+
+### Global object property
+
+At the top level, variables declared with `var`, unlike ones declared with `let` or `const`, create a property on the global object.
+
+```js
+var a = 'var';
+let b = 'let';
+
+console.log(window.a); // 'var'
+console.log(window.b); // undefined
+```
+
+### Redeclaration
+
+In strict mode, variables declared with `var` can be re-declared in the same scope, whereas this is not allowed for variables declared with `let` or `const`.
+
+```js
+'use strict';
+var a = 'var1';
+var a = 'var2';
+
+let b = 'let1';
+let b = 'let2'; // SyntaxError
+```
+
+If you want to learn more, we have [an article covering JavaScript's strict mode in more depth](/articles/s/javascript-use-strict).
diff --git a/articles/snippets/javascript-variable-hoisting.md b/articles/snippets/javascript-variable-hoisting.md
new file mode 100644
index 000000000..deb817766
--- /dev/null
+++ b/articles/snippets/javascript-variable-hoisting.md
@@ -0,0 +1,70 @@
+---
+title: What is hoisting in JavaScript?
+shortTitle: Hoisting introduction
+type: question
+tags: [javascript,type,variable]
+author: chalarangelo
+cover: boat-port
+excerpt: Hoisting comes up a lot during JavaScript interviews. It's a concept that can require some getting used to, so read our guide to learn more.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Before your JavaScript code is executed, it is first parsed and compiled. During the _compile_ phase, variable and function declarations are put into memory, which is called **hoisting**.
+
+Note that only declarations are hoisted, not initializations, meaning that if a variable is declared and initialized after using it, its value will not be initialized. This is an oversimplification of the situation, so let's take a look at the different cases:
+
+### function
+
+When using `function` declarations, the function can be called before it's defined and it will work as expected. For example:
+
+```js
+hello(); // logs 'Hello world!'
+
+function hello() {
+ console.log('Hello world!');
+}
+
+hello(); // logs 'Hello world!'
+```
+
+In the example above the `function` declaration is hoisted to the top of its scope and, due to the nature of function declarations, it's available before it's declared. However, this is the only case that behaves this way.
+
+### var
+
+`var` declarations on the other hand behave differently, returning `undefined` when accessed before initialization. For example:
+
+```js
+console.log(x); // logs 'undefined'
+f(); // throws 'Uncaught TypeError: f is not a function'
+
+var x = 1;
+var f = () => 'Hi!';
+
+console.log(x); // logs '1'
+f(); // returns 'Hi!'
+```
+
+As you can see in this example, the `var` declarations are hoisted to the top of their scope, but their values are not initialized until the code that initializes them executes, thus being `undefined` up until that point.
+
+### const and let
+
+Finally, `const` and `let` declarations are hoisted, but they are not initialized to `undefined`. Instead, they will give you an error, which is also how `class` declarations behave. For example:
+
+```js
+console.log(y); // throws 'Uncaught ReferenceError: Cannot access "y" before initialization'
+g(); // throws 'Uncaught ReferenceError: Cannot access "g" before initialization'
+
+let y = 2;
+const g = () => 'Hey!';
+
+console.log(y); // logs '2'
+f(); // returns 'Hey!'
+```
+
+Generally, `const` and `let` provide more of a headache-free experience for a variety of reasons and this is no exception. Where accessing variables declared with `var` before initialization fails silently, doing the same for `const` or `let` results in a clear, easy to debug error.
+
+### Best practices
+
+- Always define variables, functions, objects and classes before using them. ESLint can probably help you with that.
+- If your environment/team allows it, prefer `const` and `let`over `var` to minimize headaches.
+- If possible, use only arrow functions or `function` declarations. Consistency can help reduce confusion.
diff --git a/articles/snippets/javascript-variable-scope.md b/articles/snippets/javascript-variable-scope.md
new file mode 100644
index 000000000..7fb9c4715
--- /dev/null
+++ b/articles/snippets/javascript-variable-scope.md
@@ -0,0 +1,30 @@
+---
+title: Understanding JavaScript variables and scopes
+shortTitle: Variables and scopes
+type: story
+tags: [javascript,type,variable]
+author: chalarangelo
+cover: periscope
+excerpt: JavaScript developers often get confused by JavaScript's variables and scope. Here's a quick guide to understanding these concepts.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+I have seen many developers - my younger self included - struggle with JavaScript's variables and scopes, even if they have some experience with coding and/or the language itself. While there are dozens of great articles on this subject, I found it somewhat difficult to memorize or understand the way these concepts work when I was starting out, so here's a short and simple breakdown that might help you as much as it helped me.
+
+### Variable definition
+
+JavaScript provides two ways to define a variable (`var` and `let`) and one way to define a constant value (`const`).
+
+`let` and `const` behave the same in terms of scope, both being block scoped (see below). On the other hand, `var` behaves differently by being function scoped (see below), meaning `var` declarations inside a block scope will also be available to the nearest outer function block.
+
+It is generally preferred to use `let` and `const` to avoid confusion when it comes to scoping. However, it is important to note that `var` can be a useful JavaScript feature when used in the correct circumstances.
+
+
+
+### Scope
+
+When we talk about scope, we mean the visibility of one or more entities (e.g variables) to certain parts of our code. There are two types of scopes: global and local. Local scope can in turn be separated into block, function and other types of more specific scopes.
+
+**Global scope**: Variables defined globally (i.e. not inside a block or function) are part of the global scope and can be accessed from anywhere in the code. When declared in the global scope, `var`, `let` and `const` behave the same in terms of scope.
+
+**Local scope**: Variables defined inside a block or function can only be accessed from the block or function where they were defined, as well as nested local scopes. When declared inside a block scope, `var` will be available but `undefined` in outer scopes, while `let` and `const` will not exist in outer scopes. When declared inside a function scope, `var`, `let` and `const` will all be non-existent in outer scopes.
diff --git a/articles/snippets/javascript-void-links.md b/articles/snippets/javascript-void-links.md
new file mode 100644
index 000000000..90c5d512f
--- /dev/null
+++ b/articles/snippets/javascript-void-links.md
@@ -0,0 +1,18 @@
+---
+title: "Tip: Avoid \"javascript:void(0)\" for empty links"
+shortTitle: Avoid "javascript:void(0)" for empty links
+type: tip
+tags: [javascript,browser,accessibility]
+author: chalarangelo
+cover: white-flower
+excerpt: There are many ways to create empty links, some more appropriate than others. Learn how to best handle empty links with this quick tip.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+There are various ways to create an empty link, but some options are more appropriate than others. One of the most common debates about it is if one should use `href=""`, `href="#"` or `href="javascript:void(0)"`.
+
+Generally, you want to avoid `href="javascript:void(0)"`, as it will cause the browser to parse the value of the link URL, which is both costly and unnecessary. It also introduces a potential XSS security vulnerability, as `javascript:` URLs violate Content Security Policy (CSP).
+
+With that out of the way, it's clear that `href=""` or `href="#"` should be preferred in most cases. One key difference between the two is that `href="#"` points to the top of the page whereas `href=""` points to the current page. This can have unwanted side-effects, such as scrolling to the top of the page or issues with link styling respectively. To prevent either one of them from acting as links, you can use `Event.preventDefault()` and handle them appropriately using JavaScript.
+
+Finally, when creating an empty link, one should always consider more semantically appropriate alternatives, such as a ``, `` or `
` tag. After all, a link should always behave like a link and hijacking it with JavaScript or any other means is bound to run into some accessibility problems sooner or later.
diff --git a/articles/snippets/jest-mock-global-methods.md b/articles/snippets/jest-mock-global-methods.md
new file mode 100644
index 000000000..e34a718b9
--- /dev/null
+++ b/articles/snippets/jest-mock-global-methods.md
@@ -0,0 +1,21 @@
+---
+title: Mocking global object methods in Jest
+type: story
+tags: [javascript,testing]
+author: chalarangelo
+cover: trippy-chemicals
+excerpt: Testing your code is important, but mocking can be tricky at times. Here's a quick guide on how to mock global object methods in Jest.
+dateModified: 2022-03-27T05:00:00-04:00
+---
+
+Testing is a big part of the development process. It's also where a lot of mistakes can be overlooked, which can pile up and lead to hard-to-debug issues. A common problem is poorly-written mocks, especially regarding global objects and their methods. Let's take a look at how to mock global object methods in Jest.
+
+When mocking global object methods in Jest, the optimal way to do so is using the `jest.spyOn()` method. It takes the object and name of the method you want to mock, and returns a mock function. The resulting mock function can then be chained to a mocked implementation or a mocked return value. For example:
+
+```js
+jest.spyOn(Math, 'random').mockReturnValue(0.123456789);
+
+jest.spyOn(Date, 'now').mockReturnValue('123456789');
+```
+
+In this example, we mock two global object methods and return a fixed value. You could as easily mock their implementation using `mockFn.mockImplementation()`. Using either of these options allows you to get predictable values from the mocked methods. This comes in especially handy when working, for example, with `Math.random()` or `Date.now()`.
diff --git a/articles/snippets/js-abort-fetch.md b/articles/snippets/js-abort-fetch.md
new file mode 100644
index 000000000..f9e9ba90c
--- /dev/null
+++ b/articles/snippets/js-abort-fetch.md
@@ -0,0 +1,26 @@
+---
+title: "Tip: Abort a fetch request in JavaScript"
+shortTitle: Abort a fetch request
+type: story
+tags: [javascript,function]
+author: chalarangelo
+cover: cancel-typographer
+excerpt: Aborting a fetch request in JavaScript is a common problem. Here's how to handle it correctly.
+dateModified: 2022-05-15T05:00:00-04:00
+---
+
+The Fetch API is nowadays the de facto way to send asynchronous requests in JavaScript. This is in part due to the fact that the `fetch()` method accepts a multitude of useful options. One of these is the `signal` option, which can be used to abort a request. To create a valid value for this option, you can use `AbortController.signal` after creating a new instance of `AbortController`. Then, you can use `AbortController.abort()` to cancel the request at any time.
+
+```js
+// Create the AbortController
+const controller = new AbortController();
+const { signal } = controller;
+
+// Perform the request
+fetch('https://my.site.com/data', { signal }).then(res => console.log(res));
+
+// Abort the request
+controller.abort();
+```
+
+This is particularly useful in scenarios where a request takes too long or the response is no longer needed. You can see a common React use-case for this in the [useFetch hook](https://www.30secondsofcode.org/react/s/use-fetch).
diff --git a/articles/snippets/js-append-elements-to-array.md b/articles/snippets/js-append-elements-to-array.md
new file mode 100644
index 000000000..639115948
--- /dev/null
+++ b/articles/snippets/js-append-elements-to-array.md
@@ -0,0 +1,76 @@
+---
+title: Append elements to a JavaScript array
+shortTitle: Append elements to array
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: switzerland-night
+excerpt: Have you ever tried appending elements to an array in JavaScript? Here's a primer on all the available options.
+dateModified: 2022-07-10T05:00:00-04:00
+---
+
+Appending a value or values from an array in JavaScript is a pretty common task. While not hard to accomplish, there are a few approaches available, each with their own pros and cons. Choosing the correct one ultimately depends on the use case.
+
+### Array.prototype.push()
+
+The classical way to append elements to the end of an array is to use `Array.prototype.push()`. While versatile, you need to remember that it **mutates the original array**. On the flip side, it supports adding multiple elements at once. Finally, the return value of `Array.prototype.push()` is the new length of the array.
+
+```js
+const arr = ['a', 'b', 'c'];
+arr.push('d', 'e'); // Returns 5 (new length after appending 2 elements)
+// arr = ['a', 'b', 'c', 'd', 'e']
+```
+
+### Array.prototype.unshift()
+
+Similar to `Array.prototype.push()`, `Array.prototype.unshift()` appends elements to the start of an array. Furthermore, this method also **mutates the original array** and supports adding multiple elements at once.
+
+```js
+const arr = ['a', 'b', 'c'];
+arr.unshift('d', 'e'); // Returns 5 (new length after appending 2 elements)
+// arr = ['d', 'e', 'a', 'b', 'c']
+```
+
+### Array.prototype.splice()
+
+`Array.prototype.splice()` is more often used for removing elements from an array, but it can append elements, too. While it also **mutates the original array**, it can append elements anywhere in the array. Similar to previous methods, it supports adding more than one element at once. The return value of this method is practically meaningless in this use-case.
+
+```js
+const arr = ['a', 'b', 'c'];
+arr.splice(1, 0, 'd', 'e');
+// arr = ['a', 'd', 'e', 'b', 'c']
+```
+
+### Array.prototype.length
+
+Appending an element to the end of an array means setting a value for an index equal to its length. This is due to arrays in JavaScript being zero-indexed. Luckily, `Array.prototype.length` can be combined with array index notation to accomplish this. Same as previous methods, this approach **mutates the original array**. Additionally, it's limited to adding one element at a time and only at the end of the array.
+
+```js
+const arr = ['a', 'b', 'c'];
+arr[arr.length] = 'd';
+// arr = ['a', 'b', 'c', 'd']
+```
+
+### Array.prototype.concat()
+
+The first option that **doesn't mutate the original array** is `Array.prototype.concat()`. This method returns a new array with the elements of the original array and new elements concatenated to it. It can be used to append elements to either end of the array, while also supporting adding multiple elements at once.
+
+```js
+const arr = ['a', 'b', 'c'];
+const arr2 = arr.concat('d', 'e');
+// arr = ['a', 'b', 'c'], arr2 = ['a', 'b', 'c', 'd', 'e']
+const arr3 = ['d', 'e'].concat(...arr);
+// arr = ['a', 'b', 'c'], arr3 = ['d', 'e', 'a', 'b', 'c']
+```
+
+### Spread operator
+
+Finally, the last option that **doesn't mutate the original array** is the spread operator (`...`). The way that it works is essentially the same as `Array.prototype.concat()`, supporting appending one or more elements to either end of the array.
+
+```js
+const arr = ['a', 'b', 'c'];
+const arr2 = [...arr, 'd', 'e'];
+// arr = ['a', 'b', 'c'], arr2 = ['a', 'b', 'c', 'd', 'e']
+const arr3 = ['d', 'e', ...arr];
+// arr = ['a', 'b', 'c'], arr3 = ['d', 'e', 'a', 'b', 'c']
+```
diff --git a/articles/snippets/js-array-filtering-tips.md b/articles/snippets/js-array-filtering-tips.md
new file mode 100644
index 000000000..7a937c2fe
--- /dev/null
+++ b/articles/snippets/js-array-filtering-tips.md
@@ -0,0 +1,57 @@
+---
+title: JavaScript array filtering tips
+shortTitle: Array filtering tips
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: violin
+excerpt: A few tips and tricks to help you filter arrays in JavaScript more efficiently.
+dateModified: 2022-09-28T05:00:00-04:00
+---
+
+While `Array.prototype.filter()` is a very convenient method, its performance often leaves something to be desired. This is exaggerated due to the fact that it has become the go-to method for many operations that can be performed using different alternatives. Let's look at a couple of common scenarios and see how we can improve their performance.
+
+### Find a single value
+
+If you are looking for a single result in an array, you can use `Array.prototype.find()` instead. This will return the first element that satisfies the condition, or `undefined` if no such element exists. It's much faster than `Array.prototype.filter()`, as it will stop iterating as soon as it finds the first matching element.
+
+```js
+const arr = [1, 2, 3, 4, 5];
+
+arr.find(x => x > 3); // 4
+```
+
+Additionally, if the condition is a simple equality check, you can also use `Array.prototype.indexOf()`. While not as pretty as the other two, it can be significantly faster, as there's no overhead from using a comparator function.
+
+```js
+const arr = [1, 2, 3, 4, 5];
+
+arr.indexOf(3); // 2
+```
+
+### Remove a single value
+
+Similarly, if you want to remove a single value from an array, you can use `Array.prototype.findIndex()` to find the index of the element you want to remove. Then, use `Array.prototype.slice()` to remove it. While this is a little more verbose and seems to perform more operations, it can actually be faster than using `Array.prototype.filter()` in many cases.
+
+```js
+const arr = [1, 2, 3, 4, 5];
+
+const index = arr.findIndex(x => x === 3);
+const newArr = [...arr.slice(0, index), ...arr.slice(index + 1)];
+// [1, 2, 4, 5]
+```
+
+Similarly, if you don't mind mutating the original array, you can use `Array.prototype.splice()` to remove the element at the index you found. As this method doesn't have to create a new array, it can be significantly faster than the previous one.
+
+```js
+const arr = [1, 2, 3, 4, 5];
+
+const index = arr.findIndex(x => x === 3);
+arr.splice(index, 1); // [1, 2, 4, 5]
+```
+
+### Additional notes
+
+In many cases, such changes will not make a drastic difference in your application's performance. It never hurts, however, to be aware of all the options and use the best one for your specific use case. Changes such as these will make more sense when working with large datasets, as well as critical parts of your application.
+
+Additionally, depending on the data and its constraints, it might make more sense to use a different data structure altogether. For example, if unique values are a precondition, using a `Set` is more efficient and much easier to work with in many cases.
diff --git a/articles/snippets/js-array-map-vs-foreach.md b/articles/snippets/js-array-map-vs-foreach.md
new file mode 100644
index 000000000..df3b4d0ee
--- /dev/null
+++ b/articles/snippets/js-array-map-vs-foreach.md
@@ -0,0 +1,30 @@
+---
+title: What is the difference between Array.prototype.map() and Array.prototype.forEach()?
+shortTitle: Array.prototype.map() vs Array.prototype.forEach()
+type: question
+tags: [javascript,array]
+author: chalarangelo
+cover: fort-lamp
+excerpt: Which method do you reach for first? What are the differences between them? Let's find out!
+dateModified: 2023-03-26T05:00:00-04:00
+---
+
+`Array.prototype.map()` and `Array.prototype.forEach()` are two of the most commonly used methods in JavaScript. Both of them iterate over an array and perform some action on each element. Yet, they're not the same and they're not interchangeable.
+
+The key difference between the two lies in the **return value**. The return value of `Array.prototype.map()` is a new array with the results of the callback function. On the other hand, the return value of `Array.prototype.forEach()` is `undefined`.
+
+Simply put, `Array.prototype.forEach()` is used to perform some action on each element in an array, while `Array.prototype.map()` is used to create a new array based on the elements in the original array. Let's take a look at an example to clear up any confusion:
+
+```js
+const numbers = [1, 2, 3, 4, 5];
+
+numbers.forEach(num => console.log(num * 2));
+// No return value, output: 2, 4, 6, 8, 10
+
+const doubledNumbers = numbers.map(num => num * 2);
+// Returns a new array: [2, 4, 6, 8, 10]
+```
+
+The way I like to distinguish them is by remembering that `Array.prototype.map()` represents a **transformation**, whereas `Array.prototype.forEach()` represents an **iteration**. Hopefully, one of these explanations will click for you and help you remember the difference between the two.
+
+As a closing note, I would like to remind you that the humble `for` loop can be more efficient in some cases, such as [breaking out of a loop early](/articles/s/javascript-for-loop-early-break). Always pick the right tool for the job, as ES6 has a method for almost every use case.
diff --git a/articles/snippets/js-array-min-max.md b/articles/snippets/js-array-min-max.md
new file mode 100644
index 000000000..463102c6b
--- /dev/null
+++ b/articles/snippets/js-array-min-max.md
@@ -0,0 +1,21 @@
+---
+title: "Tip: Min and max value in a JavaScript array"
+shortTitle: Min and max value of an array
+type: tip
+tags: [javascript,array,math]
+author: chalarangelo
+cover: little-tree
+excerpt: When working with numeric arrays in JavaScript, you might need to find the minimum or maximum value. Here's a quick and easy way to do it.
+dateModified: 2021-11-06T20:51:47+03:00
+---
+
+When working with numeric arrays in JavaScript, you might find yourself in need of finding the minimum or maximum value. Luckily, JavaScript's `Math` built-in object has got you covered. You can simply use `Math.min()` or `Math.max()` combined with the spread operator (`...`), as both functions accept any number of arguments.
+
+```js
+const nums = [2, 4, 6, 8, 1, 3, 5, 7];
+
+Math.max(...nums); // 8
+Math.min(...nums); // 1
+```
+
+For more complex cases, such as finding the min/max value in an array of objects, you might have to resort to `Array.prototype.map()` or `Array.prototype.reduce()`. On the other hand, our [minBy](/js/s/min-by) or [maxBy](/js/s/max-by) snippets might be all you need.
diff --git a/articles/snippets/js-array-sorting-shorthand.md b/articles/snippets/js-array-sorting-shorthand.md
new file mode 100644
index 000000000..3226fc242
--- /dev/null
+++ b/articles/snippets/js-array-sorting-shorthand.md
@@ -0,0 +1,41 @@
+---
+title: "Tip: JavaScript array sorting shorthand"
+shortTitle: Array sorting shorthand
+type: tip
+tags: [javascript,array]
+cover: apples
+excerpt: Learn how to quickly write code to sort JavaScript arrays with this handy one-liner.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+When sorting an array of primitive values (e.g. strings or numbers), you'll often see a lot of code that looks like this:
+
+```js
+const arr = [8, 2, 1, 4, 5, 0];
+// Sort in ascending order
+arr.sort((a, b) => {
+ if (a > b) return 1;
+ if (b > a) return -1
+ return 0;
+}); // [0, 1, 2, 4, 5, 8]
+```
+
+While this piece of code does the job, there is also a one-line alternative for it. The trick hinges on `Array.prototype.sort()` expecting either a positive or a negative value to perform a swap between two elements, thus allowing for more flexible values than `1` and `-1`. Subtracting the numeric values in an array is sufficient and can also be used to sort the array the other way around:
+
+```js
+const arr = [8, 2, 1, 4, 5, 0];
+// Sort in ascending order
+arr.sort((a, b) => a - b); // [0, 1, 2, 4, 5, 8]
+// Sort in descending order
+arr.sort((a, b) => b - a); // [8, 5, 4, 2, 1, 0]
+```
+
+If you are working with string arrays, you should instead use `String.prototype.localeCompare()`, as it provides far greater flexibility, by accounting for specific locales and their unique needs:
+
+```js
+const s = ['Hi', 'Hola', 'Hello'];
+// Sort in ascending order
+arr.sort((a, b) => a.localeCompare(b)); // ['Hello', 'Hi', 'Hola']
+// Sort in descending order
+arr.sort((a, b) => b.localeCompare(a)); // ['Hola', 'Hi', 'Hello']
+```
diff --git a/articles/snippets/js-async-defer.md b/articles/snippets/js-async-defer.md
new file mode 100644
index 000000000..c069b3b71
--- /dev/null
+++ b/articles/snippets/js-async-defer.md
@@ -0,0 +1,42 @@
+---
+title: What is the difference between async and defer in script loading?
+shortTitle: Async and defer
+type: question
+tags: [javascript,html]
+author: chalarangelo
+cover: coworking-space
+excerpt: Understanding how to correctly load your JavaScript files can significantly improve your web application's performance.
+dateModified: 2022-09-04T05:00:00-04:00
+---
+
+When it comes to loading JavaScript files, there are a few different options available. Understanding exactly how scripts are loaded and executed is crucial for website performance, as well as for the overall quality of the user experience. Let's take a look at how the `
+```
+
+As you can see, this method can cause a long pause in HTML parsing, resulting in a degraded user experience.
+
+### The async attribute
+
+To avoid a long pause in HTML parsing, the `async` attribute can be leveraged. This ensures that, when the script is encountered, parsing doesn't pause right away. Instead, the script is loaded in the background and only the HTML parsing is paused to execute it. HTML parsing resumes as usual after script execution is completed.
+
+```html
+
+```
+
+While the `async` attribute takes steps to mitigate the issue mentioned previously, it comes with an important caveat. Scripts loaded this way are not guaranteed to execute in the order specified, but rather as they become available when they are loaded.
+
+### The defer attribute
+
+Finally, the `defer` attribute builds on top of the previous behavior to guarantee order of execution for scripts. As previously, scripts are loaded in the background as they are encountered. When the HTML parsing finishes, they are then executed in order.
+
+```html
+
+```
diff --git a/articles/snippets/js-callbacks.md b/articles/snippets/js-callbacks.md
new file mode 100644
index 000000000..14ad8b45d
--- /dev/null
+++ b/articles/snippets/js-callbacks.md
@@ -0,0 +1,34 @@
+---
+title: What is a callback function?
+shortTitle: Callback functions
+type: question
+tags: [javascript,function]
+author: chalarangelo
+cover: rabbit-call
+excerpt: JavaScript uses callback functions quite a lot. From event listeners to asynchronous code, they're an invaluable tool you need to master.
+dateModified: 2021-10-03T05:00:00-04:00
+---
+
+A callback function is a function passed as an argument to another function, which is then invoked inside the outer function. Callback functions are often executed once an event has occurred or a task has completed.
+
+### Synchronous callbacks
+
+A synchronous callback is a callback function that is executed immediately. The function passed as the first argument to `Array.prototype.map()` is a great example of a synchronous callback:
+
+```js
+const nums = [1, 2, 3];
+const printDoublePlusOne = n => console.log(2 * n + 1);
+
+nums.map(printDoublePlusOne); // LOGS: 3, 5, 7
+```
+
+### Asynchronous callbacks
+
+An asynchronous callback is a callback function that is used to execute code after an asynchronous operation has completed. The function executed inside `Promise.prototype.then()` is a great example of an asynchronous callback:
+
+```js
+const nums = fetch('https://api.nums.org'); // Suppose the response is [1, 2, 3]
+const printDoublePlusOne = n => console.log(2 * n + 1);
+
+nums.then(printDoublePlusOne); // LOGS: 3, 5, 7
+```
diff --git a/articles/snippets/js-cannot-extend-proxy-object.md b/articles/snippets/js-cannot-extend-proxy-object.md
new file mode 100644
index 000000000..93c044328
--- /dev/null
+++ b/articles/snippets/js-cannot-extend-proxy-object.md
@@ -0,0 +1,32 @@
+---
+title: "Tip: You can't extend the Proxy object"
+shortTitle: Extending the Proxy object
+type: tip
+tags: [javascript,object,proxy]
+author: chalarangelo
+cover: icebreaker
+excerpt: Turns out the Proxy object is not extensible, but there's a way around its limitations.
+dateModified: 2023-04-17T05:00:00-04:00
+---
+
+While the [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) object seems like it can be extended by any other class in JavaScript, that's not the case. This is due to proxy objects having very atypical semantics and being considered **exotic objects**. Simply put, this means they do not have a prototype and are not extensible.
+
+So how do you extend a proxy object? You don't. You can, however, create a class that returns a proxy by returning it from the constructor. After all, this is probably the sort of behavior you're after.
+
+```js
+class MyProxy {
+ constructor(value) {
+ Object.keys(value).forEach(key => (this[key] = value[key]));
+ return new Proxy(this, {
+ set(object, key, value) {
+ console.log(`Called with ${key} = ${value}`);
+ object[key] = value;
+ return true;
+ }
+ });
+ }
+}
+
+const myProxy = new MyProxy({ a: 1 });
+myProxy.b = 2; // LOGS: 'Called with b = 2'
+```
diff --git a/articles/snippets/js-compare-string-case-accent-insensitive.md b/articles/snippets/js-compare-string-case-accent-insensitive.md
new file mode 100644
index 000000000..81296b956
--- /dev/null
+++ b/articles/snippets/js-compare-string-case-accent-insensitive.md
@@ -0,0 +1,26 @@
+---
+title: "Tip: Compare strings regardless of case and accent"
+shortTitle: Case and accent-insensitive string comparison
+type: tip
+tags: [javascript,string,comparison]
+author: chalarangelo
+cover: memories-of-pineapple-1
+excerpt: Here's a quick tip on how to compare and sort arrays of strings, ignoring case and accents.
+dateModified: 2022-07-17T05:00:00-04:00
+---
+
+Comparing and sorting JavaScript strings is rather common. Usually, the use of `String.prototype.localeCompare()` is sufficient for sorting arrays of strings in most scenarios. Dealing with accents and cases can get tricky, however, and lead to unexpected results. This is where `Intl.Collator` comes into play, an object used for language-sensitive string comparison. Using `Intl.Collator.prototype.compare()`, you can sort strings regardless of their case or accent and it can even accept a locale argument.
+
+```js
+const arr = ['ä', 'a', 'b', 'A', 'B', 'Å'];
+
+const localeCompare = (a, b) => a.localeCompare(b);
+const collator = new Intl.Collator();
+const deCollator = new Intl.Collator('de');
+const svCollator = new Intl.Collator('sv');
+
+arr.sort(localeCompare); // ['a', 'A', 'Å', 'ä', 'b', 'B']
+arr.sort(collator.compare); // ['a', 'A', 'Å', 'ä', 'b', 'B']
+arr.sort(deCollator.compare); // ['a', 'A', 'Å', 'ä', 'b', 'B']
+arr.sort(svCollator.compare); // ['a', 'A', 'b', 'B', 'Å', 'ä']
+```
diff --git a/articles/snippets/js-construct-url.md b/articles/snippets/js-construct-url.md
new file mode 100644
index 000000000..5bc192d7f
--- /dev/null
+++ b/articles/snippets/js-construct-url.md
@@ -0,0 +1,65 @@
+---
+title: How to construct a URL in JavaScript
+shortTitle: Construct a URL in JavaScript
+type: story
+tags: [javascript,string,browser]
+author: chalarangelo
+cover: alfama
+excerpt: A short guide on how to correctly construct a URL in JavaScript.
+dateModified: 2023-02-26T05:00:00-04:00
+---
+
+Oftentimes, we need to **create a URL in JavaScript**, to request a resource or redirect the user. A seemingly simple task, yet URLs can be quite nuanced and complex, requiring a lot of attention to get right. This rings especially true if you've ever worked with different encodings and multiple **query parameters**.
+
+Naively, many developers reach for template literals to construct a URL. After all, URLs are simply strings and interpolation can be used to add parameters as needed. Except, this approach is error-prone and can lead to bugs. Let's take a look at an example:
+
+```js
+const query = "Where's Waldø?";
+const locale = "en-US";
+const campaign = "promo_email";
+
+const url = `https://examp.le?q=${query}&lang=${locale}&from=${campaign}`;
+// "https://examp.le?q=Where's Waldø?&lang=en-US&from=promo_email"
+```
+
+As you can see, template literals aren't well-suited for URLs, as they won't **encode special characters**. If you've worked with JavaScript for any amount of time, you might reach for `encodeURIComponent()` to fix this:
+
+```js
+const query = "Where's Waldø?";
+const locale = "en-US";
+const campaign = "promo_email";
+
+const url = `https://examp.le
+ ?q=${
+ encodeURIComponent(query)
+ }&lang=${
+ encodeURIComponent(locale)
+ }&from=${
+ encodeURIComponent(campaign)
+ }`;
+// "https://examp.le\n ?q=Where's%20Wald%C3%B8%3F&lang=en-US&from=promo_email"
+```
+
+Surely, this dealt with encoding, but the multiline string has sneaked a newline character (`\n`) into the URL. This is because template literals preserve whitespace, leading to such issues. Breaking the string into multiple lines and concatenating them can help, but the code is starting to get ugly.
+
+Obviously, there are other issues that might come into play, making this a **non-trivial problem** to solve. Luckily, there's a better way to construct URLs in JavaScript, using the `URL` object. Let's see how we can use it to solve the problem above:
+
+```js
+const query = "Where's Waldø?";
+const locale = "en-US";
+const campaign = "promo_email";
+
+// Good
+const url = new URL('https://examp.le');
+
+url.searchParams.set('q', query);
+url.searchParams.set('lang', locale);
+url.searchParams.set('from', campaign);
+
+url.toString();
+// 'https://examp.le/?q=Where%27s+Wald%C3%B8%3F&lang=en-US&from=promo_email'
+```
+
+Admittedly, using the `URL` object can be a bit more verbose, but it's a worthwhile tradeoff. The code is much more readable and maintainable, and it's less prone to errors. Query parameters are now encoded properly, and delimiters are added automatically.
+
+While query parameters are the most common issue when dealing with URLs, the `URL` object can be useful in many other situations. For example, you can change the protocol, hostname, port, path, hash, etc. of a URL, or even parse an existing URL into its components. If you're interested, you should check out previous articles about how you can [edit URL parameters](/articles/s/js-edit-url-params) and the [`window.location` cheat sheet](/articles/s/js-window-location-cheatsheet).
diff --git a/articles/snippets/js-create-element.md b/articles/snippets/js-create-element.md
new file mode 100644
index 000000000..8e3ae1aa8
--- /dev/null
+++ b/articles/snippets/js-create-element.md
@@ -0,0 +1,58 @@
+---
+title: Creating HTML elements in JavaScript
+shortTitle: Creating HTML elements
+type: story
+tags: [javascript,browser]
+author: chalarangelo
+cover: body-of-water
+excerpt: Learn how to create HTML elements in JavaScript, by abstracting the creation logic into a function.
+dateModified: 2022-05-29T05:00:00-04:00
+---
+
+JavaScript's `Document.createElement()` method is used to create new HTML elements. Here's what that looks like in action:
+
+```js
+const root = document.body;
+
+const newElement = document.createElement('div');
+newElement.textContent = 'Hello World';
+
+root.append(newElement);
+```
+
+As you can see, creating an element is easy. The tiresome part is having to set all of its attributes and then add it to the DOM. Worse even, creating multiple elements with the same set of attributes requires a lot of repetitive code.
+
+Luckily, we can abstract element creation into a function. In fact, we can use objects to pass attributes to the element. Using `Object.entries()` we can iterate over the object and set the attributes. Here's what that looks like:
+
+```js
+const root = document.body;
+
+const createElement = (el, parent, prepend = false) => {
+ const { nodeName = 'div', ...attrs } = el;
+ const element = document.createElement(nodeName);
+ Object.entries(attrs).forEach(([attr, value]) => {
+ element[attr] = value;
+ });
+ if (prepend) parent.prepend(element);
+ else parent.append(element);
+};
+
+createElement(
+ {
+ nodeName: 'div',
+ textContent: 'Hello world',
+ },
+ root
+);
+
+createElement(
+ {
+ nodeName: 'p',
+ textContent: 'Hi',
+ },
+ root,
+ true
+);
+```
+
+That's pretty useful, but what happens if we have an HTML string we want to create an element from, instead? We have a [createElement snippet](/js/s/create-element) that does something along those lines. The only part that's missing is appending it to the parent element.
diff --git a/articles/snippets/js-data-structures-binary-search-tree.md b/articles/snippets/js-data-structures-binary-search-tree.md
new file mode 100644
index 000000000..8ac363da8
--- /dev/null
+++ b/articles/snippets/js-data-structures-binary-search-tree.md
@@ -0,0 +1,217 @@
+---
+title: JavaScript Data Structures - Binary Search Tree
+shortTitle: Binary Search Tree
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-4
+excerpt: A binary search tree is a hierarchical data structure of ordered nodes with at most two children each.
+dateModified: 2021-08-31T05:00:00-04:00
+---
+
+### Definition
+
+A binary search tree is a data structure consisting of a set of ordered linked nodes that represent a hierarchical tree structure. Each node is linked to others via parent-children relationship. Any given node can have at most two children (left and right). The first node in the binary search tree is the root, whereas nodes without any children are the leaves. The binary search tree is organized in such a way that for any given node, all nodes in its left subtree have a key less than itself and all nodes in its right subtree have a key greater than itself.
+
+
+
+Each node in a binary search tree data structure must have the following properties:
+
+- `key`: The key of the node
+- `value`: The value of the node
+- `parent`: The parent of the node (`null` if there is none)
+- `left`: A pointer to the node's left child (`null` if there is none)
+- `right`: A pointer to the node's right child (`null` if there is none)
+
+The main operations of a binary search tree data structure are:
+
+- `insert`: Inserts a node as a child of the given parent node
+- `remove`: Removes a node and its children from the binary search tree
+- `has`: Checks if a given node exists
+- `find`: Retrieves a given node
+- `preOrderTraversal`: Traverses the binary search tree by recursively traversing each node followed by its children
+- `postOrderTraversal`: Traverses the binary search tree by recursively traversing each node's children followed by the node
+- `inOrderTraversal`: Traverses the binary search tree by recursively traversing each node's left child, followed by the node, followed by its right child
+
+### Implementation
+
+```js
+class BinarySearchTreeNode {
+ constructor(key, value = key, parent = null) {
+ this.key = key;
+ this.value = value;
+ this.parent = parent;
+ this.left = null;
+ this.right = null;
+ }
+
+ get isLeaf() {
+ return this.left === null && this.right === null;
+ }
+
+ get hasChildren() {
+ return !this.isLeaf;
+ }
+}
+
+class BinarySearchTree {
+ constructor(key, value = key) {
+ this.root = new BinarySearchTreeNode(key, value);
+ }
+
+ *inOrderTraversal(node = this.root) {
+ if (node.left) yield* this.inOrderTraversal(node.left);
+ yield node;
+ if (node.right) yield* this.inOrderTraversal(node.right);
+ }
+
+ *postOrderTraversal(node = this.root) {
+ if (node.left) yield* this.postOrderTraversal(node.left);
+ if (node.right) yield* this.postOrderTraversal(node.right);
+ yield node;
+ }
+
+ *preOrderTraversal(node = this.root) {
+ yield node;
+ if (node.left) yield* this.preOrderTraversal(node.left);
+ if (node.right) yield* this.preOrderTraversal(node.right);
+ }
+
+ insert(key, value = key) {
+ let node = this.root;
+ while (true) {
+ if (node.key === key) return false;
+ if (node.key > key) {
+ if (node.left !== null) node = node.left;
+ else {
+ node.left = new BinarySearchTreeNode(key, value, node);
+ return true;
+ }
+ } else if (node.key < key) {
+ if (node.right !== null) node = node.right;
+ else {
+ node.right = new BinarySearchTreeNode(key, value, node);
+ return true;
+ }
+ }
+ }
+ }
+
+ has(key) {
+ for (let node of this.postOrderTraversal()) {
+ if (node.key === key) return true;
+ }
+ return false;
+ }
+
+ find(key) {
+ for (let node of this.postOrderTraversal()) {
+ if (node.key === key) return node;
+ }
+ return undefined;
+ }
+
+ remove(key) {
+ const node = this.find(key);
+ if (!node) return false;
+ const isRoot = node.parent === null;
+ const isLeftChild = !isRoot ? node.parent.left === node : false;
+ const hasBothChildren = node.left !== null && node.right !== null;
+
+ if (node.isLeaf) {
+ if (!isRoot) {
+ if (isLeftChild) node.parent.left = null;
+ else node.parent.right = null;
+ } else {
+ this.root = null;
+ }
+ return true;
+ } else if (!hasBothChildren) {
+ const child = node.left !== null ? node.left : node.right;
+ if (!isRoot) {
+ if (isLeftChild) node.parent.left = child;
+ else node.parent.right = child;
+ } else {
+ this.root = child;
+ }
+ child.parent = node.parent;
+ return true;
+ } else {
+ const rightmostLeft = [...this.inOrderTraversal(node.left)].slice(-1)[0];
+ rightmostLeft.parent = node.parent;
+ if (!isRoot) {
+ if (isLeftChild) node.parent.left = rightmostLeft;
+ else node.parent.right = rightmostLeft;
+ } else {
+ this.root = rightmostLeft;
+ }
+ rightmostLeft.right = node.right;
+ node.right.parent = rightmostLeft;
+ return true;
+ }
+ }
+}
+```
+
+- Create a `class` for the `BinarySearchTreeNode` with a `constructor` that initializes the appropriate `key`, `value`, `parent`, `left` and `right` properties.
+- Define an `isLeaf` getter, that uses `Array.prototype.length` to check if both `left` and `right` are empty.
+- Define a `hasChildren` getter, that is the reverse of the `isLeaf` getter.
+- Create a `class` for the `BinarySearchTree` with a `constructor` that initializes the `root` of the binary search tree.
+- Define a `preOrderTraversal()` generator method that traverses the binary search tree in pre-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define a `postOrderTraversal()` generator method that traverses the binary search tree in post-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define a `inOrderTraversal()` generator method that traverses the binary search tree in in-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define an `insert()` method, that uses a `while` loop to search the binary search tree, moving through each node's children, until an appropriate position is found to insert a new child `BinarySearchTreeNode` either as the `left` or `right` child, depending on the given `key`.
+- Define a `has()` method, that uses the `preOrderTraversal()` method to check if the given node exists in the binary search tree.
+- Define a `find()` method, that uses the `preOrderTraversal()` method to retrieve the given node in the binary search tree.
+- Define a `remove()` method, that removes the given `BinarySearchTreeNode` from the binary search tree, deleting any links to it and updating the binary search tree to retain its order.
+
+```js
+const tree = new BinarySearchTree(30);
+
+tree.insert(10);
+tree.insert(15);
+tree.insert(12);
+tree.insert(40);
+tree.insert(35);
+tree.insert(50);
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// [30, 10, 15, 12, 40, 35, 50]
+
+[...tree.inOrderTraversal()].map(x => x.value);
+// [10, 12, 15, 30, 35, 40, 50]
+
+[...tree.postOrderTraversal()].map(x => x.value);
+// [12, 15, 10, 35, 50, 40, 30]
+
+tree.root.value; // 30
+tree.root.hasChildren; // true
+
+tree.find(12).isLeaf; // true
+tree.find(40).isLeaf; // false
+tree.find(50).parent.value; // 40
+tree.find(15).left.value; // 12
+tree.find(12).right; // null
+
+tree.remove(12);
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// [30, 10, 15, 40, 35, 50]
+
+tree.remove(10);
+
+[...tree.preOrderTraversal()].map(v => ({
+ key: v.key,
+ parent: v.parent ? v.parent.key : null,
+})); // [30, 15, 40, 35, 50]
+
+tree.remove(40);
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// [30, 15, 40, 35, 50]
+
+tree.remove(30);
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// [15, 35, 50]
+```
diff --git a/articles/snippets/js-data-structures-binary-tree.md b/articles/snippets/js-data-structures-binary-tree.md
new file mode 100644
index 000000000..b487fc65a
--- /dev/null
+++ b/articles/snippets/js-data-structures-binary-tree.md
@@ -0,0 +1,163 @@
+---
+title: JavaScript Data Structures - Binary Tree
+shortTitle: Binary Tree
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-3
+excerpt: A binary tree is a hierarchical data structure of linked nodes with at most two children each.
+dateModified: 2021-08-26T05:00:00-04:00
+---
+
+### Definition
+
+A binary tree is a data structure consisting of a set of linked nodes that represent a hierarchical tree structure. Each node is linked to others via parent-children relationship. Any given node can have at most two children (left and right). The first node in the binary tree is the root, whereas nodes without any children are the leaves.
+
+
+
+Each node in a binary tree data structure must have the following properties:
+
+- `key`: The key of the node
+- `value`: The value of the node
+- `parent`: The parent of the node (`null` if there is none)
+- `left`: A pointer to the node's left child (`null` if there is none)
+- `right`: A pointer to the node's right child (`null` if there is none)
+
+The main operations of a binary tree data structure are:
+
+- `insert`: Inserts a node as a child of the given parent node
+- `remove`: Removes a node and its children from the binary tree
+- `find`: Retrieves a given node
+- `preOrderTraversal`: Traverses the binary tree by recursively traversing each node followed by its children
+- `postOrderTraversal`: Traverses the binary tree by recursively traversing each node's children followed by the node
+- `inOrderTraversal`: Traverses the binary tree by recursively traversing each node's left child, followed by the node, followed by its right child
+
+### Implementation
+
+```js
+class BinaryTreeNode {
+ constructor(key, value = key, parent = null) {
+ this.key = key;
+ this.value = value;
+ this.parent = parent;
+ this.left = null;
+ this.right = null;
+ }
+
+ get isLeaf() {
+ return this.left === null && this.right === null;
+ }
+
+ get hasChildren() {
+ return !this.isLeaf;
+ }
+}
+
+class BinaryTree {
+ constructor(key, value = key) {
+ this.root = new BinaryTreeNode(key, value);
+ }
+
+ *inOrderTraversal(node = this.root) {
+ if (node.left) yield* this.inOrderTraversal(node.left);
+ yield node;
+ if (node.right) yield* this.inOrderTraversal(node.right);
+ }
+
+ *postOrderTraversal(node = this.root) {
+ if (node.left) yield* this.postOrderTraversal(node.left);
+ if (node.right) yield* this.postOrderTraversal(node.right);
+ yield node;
+ }
+
+ *preOrderTraversal(node = this.root) {
+ yield node;
+ if (node.left) yield* this.preOrderTraversal(node.left);
+ if (node.right) yield* this.preOrderTraversal(node.right);
+ }
+
+ insert(
+ parentNodeKey,
+ key,
+ value = key,
+ { left, right } = { left: true, right: true }
+ ) {
+ for (let node of this.preOrderTraversal()) {
+ if (node.key === parentNodeKey) {
+ const canInsertLeft = left && node.left === null;
+ const canInsertRight = right && node.right === null;
+ if (!canInsertLeft && !canInsertRight) return false;
+ if (canInsertLeft) {
+ node.left = new BinaryTreeNode(key, value, node);
+ return true;
+ }
+ if (canInsertRight) {
+ node.right = new BinaryTreeNode(key, value, node);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ remove(key) {
+ for (let node of this.preOrderTraversal()) {
+ if (node.left.key === key) {
+ node.left = null;
+ return true;
+ }
+ if (node.right.key === key) {
+ node.right = null;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ find(key) {
+ for (let node of this.preOrderTraversal()) {
+ if (node.key === key) return node;
+ }
+ return undefined;
+ }
+}
+```
+
+- Create a `class` for the `BinaryTreeNode` with a `constructor` that initializes the appropriate `key`, `value`, `parent`, `left` and `right` properties.
+- Define an `isLeaf` getter, that uses `Array.prototype.length` to check if both `left` and `right` are empty.
+- Define a `hasChildren` getter, that is the reverse of the `isLeaf` getter.
+- Create a `class` for the `BinaryTree` with a `constructor` that initializes the `root` of the binary tree.
+- Define a `preOrderTraversal()` generator method that traverses the binary tree in pre-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define a `postOrderTraversal()` generator method that traverses the binary tree in post-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define a `inOrderTraversal()` generator method that traverses the binary tree in in-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define an `insert()` method, that uses the `preOrderTraversal()` method to find the given parent node and insert a new child `BinaryTreeNode` either as the `left` or `right` child, depending on the passed options object.
+- Define a `remove()` method, that uses the `preOrderTraversal()` method and `Array.prototype.filter()` to remove a `BinaryTreeNode` from the binary tree.
+- Define a `find()` method, that uses the `preOrderTraversal()` method to retrieve the given node in the binary tree.
+
+```js
+const tree = new BinaryTree(1, 'AB');
+
+tree.insert(1, 11, 'AC');
+tree.insert(1, 12, 'BC');
+tree.insert(12, 121, 'BG', { right: true });
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// ['AB', 'AC', 'BC', 'BCG']
+
+[...tree.inOrderTraversal()].map(x => x.value);
+// ['AC', 'AB', 'BC', 'BG']
+
+tree.root.value; // 'AB'
+tree.root.hasChildren; // true
+
+tree.find(12).isLeaf; // false
+tree.find(121).isLeaf; // true
+tree.find(121).parent.value; // 'BC'
+tree.find(12).left; // null
+tree.find(12).right.value; // 'BG'
+
+tree.remove(12);
+
+[...tree.postOrderTraversal()].map(x => x.value);
+// ['AC', 'AB']
+```
diff --git a/articles/snippets/js-data-structures-doubly-linked-list.md b/articles/snippets/js-data-structures-doubly-linked-list.md
new file mode 100644
index 000000000..891ceaa14
--- /dev/null
+++ b/articles/snippets/js-data-structures-doubly-linked-list.md
@@ -0,0 +1,147 @@
+---
+title: JavaScript Data Structures - Doubly Linked List
+shortTitle: Doubly Linked List
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-4
+excerpt: A doubly linked list is a linear data structure where each element points both to the next and the previous one.
+dateModified: 2021-08-12T05:00:00-04:00
+---
+
+### Definition
+
+A doubly linked list is a linear data structure that represents a collection of elements, where each element points both to the next and the previous one. The first element in the doubly linked list is the head and the last element is the tail.
+
+
+
+Each element of a doubly linked list data structure must have the following properties:
+
+- `value`: The value of the element
+- `next`: A pointer to the next element in the linked list (`null` if there is none)
+- `previous`: A pointer to the previous element in the linked list (`null` if there is none)
+
+The main properties of a doubly linked list data structure are:
+
+- `size`: The number of elements in the doubly linked list
+- `head`: The first element in the doubly linked list
+- `tail`: The last element in the doubly linked list
+
+The main operations of a doubly linked list data structure are:
+
+- `insertAt`: Inserts an element at the specific index
+- `removeAt`: Removes the element at the specific index
+- `getAt`: Retrieves the element at the specific index
+- `clear`: Empties the doubly linked list
+- `reverse`: Reverses the order of elements in the doubly linked list
+
+### Implementation
+
+```js
+class DoublyLinkedList {
+ constructor() {
+ this.nodes = [];
+ }
+
+ get size() {
+ return this.nodes.length;
+ }
+
+ get head() {
+ return this.size ? this.nodes[0] : null;
+ }
+
+ get tail() {
+ return this.size ? this.nodes[this.size - 1] : null;
+ }
+
+ insertAt(index, value) {
+ const previousNode = this.nodes[index - 1] || null;
+ const nextNode = this.nodes[index] || null;
+ const node = { value, next: nextNode, previous: previousNode };
+
+ if (previousNode) previousNode.next = node;
+ if (nextNode) nextNode.previous = node;
+ this.nodes.splice(index, 0, node);
+ }
+
+ insertFirst(value) {
+ this.insertAt(0, value);
+ }
+
+ insertLast(value) {
+ this.insertAt(this.size, value);
+ }
+
+ getAt(index) {
+ return this.nodes[index];
+ }
+
+ removeAt(index) {
+ const previousNode = this.nodes[index - 1] || null;
+ const nextNode = this.nodes[index + 1] || null;
+
+ if (previousNode) previousNode.next = nextNode;
+ if (nextNode) nextNode.previous = previousNode;
+
+ return this.nodes.splice(index, 1);
+ }
+
+ clear() {
+ this.nodes = [];
+ }
+
+ reverse() {
+ this.nodes = this.nodes.reduce((acc, { value }) => {
+ const nextNode = acc[0] || null;
+ const node = { value, next: nextNode, previous: null };
+ if (nextNode) nextNode.previous = node;
+ return [node, ...acc];
+ }, []);
+ }
+
+ *[Symbol.iterator]() {
+ yield* this.nodes;
+ }
+}
+```
+
+- Create a `class` with a `constructor` that initializes an empty array, `nodes`, for each instance.
+- Define a `size` getter, that returns that uses `Array.prototype.length` to return the number of elements in the `nodes` array.
+- Define a `head` getter, that returns the first element of the `nodes` array or `null` if empty.
+- Define a `tail` getter, that returns the last element of the `nodes` array or `null` if empty.
+- Define an `insertAt()` method, which uses `Array.prototype.splice()` to add a new object in the `nodes` array, updating the `next` and `previous` keys of the previous and next elements respectively.
+- Define two convenience methods, `insertFirst()` and `insertLast()` that use the `insertAt()` method to insert a new element at the start or end of the `nodes` array respectively.
+- Define a `getAt()` method, which retrieves the element in the given `index`.
+- Define a `removeAt()` method, which uses `Array.prototype.splice()` to remove an object in the `nodes` array, updating the `next` and `previous` keys of the previous and next elements respectively.
+- Define a `clear()` method, which empties the `nodes` array.
+- Define a `reverse()` method, which uses `Array.prototype.reduce()` and the spread operator (`...`) to reverse the order of the `nodes` array, updating the `next` and `previous` keys of each element appropriately.
+- Define a generator method for `Symbol.iterator`, which delegates to the `nodes` array's iterator using the `yield*` syntax.
+
+```js
+const list = new DoublyLinkedList();
+
+list.insertFirst(1);
+list.insertFirst(2);
+list.insertFirst(3);
+list.insertLast(4);
+list.insertAt(3, 5);
+
+list.size; // 5
+list.head.value; // 3
+list.head.next.value; // 2
+list.tail.value; // 4
+list.tail.previous.value; // 5
+[...list.map(e => e.value)]; // [3, 2, 1, 5, 4]
+
+list.removeAt(1); // 2
+list.getAt(1).value; // 1
+list.head.next.value; // 1
+[...list.map(e => e.value)]; // [3, 1, 5, 4]
+
+list.reverse();
+[...list.map(e => e.value)]; // [4, 5, 1, 3]
+
+list.clear();
+list.size; // 0
+```
diff --git a/articles/snippets/js-data-structures-graph.md b/articles/snippets/js-data-structures-graph.md
new file mode 100644
index 000000000..0e6817a55
--- /dev/null
+++ b/articles/snippets/js-data-structures-graph.md
@@ -0,0 +1,168 @@
+---
+title: JavaScript Data Structures - Graph
+shortTitle: Graph
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-1
+excerpt: A graph is a data structure consisting of a set of vertices connected by a set of edges.
+dateModified: 2021-08-17T05:00:00-04:00
+---
+
+### Definition
+
+A graph is a data structure consisting of a set of nodes or vertices and a set of edges that represent connections between those nodes. Graphs can be directed or undirected, while their edges can be assigned numeric weights.
+
+
+
+Each node in a graph data structure must have the following properties:
+
+- `key`: The key of the node
+- `value`: The value of the node
+
+Each edge in a graph data structure must have the following properties:
+
+- `a`: The starting node of the edge
+- `b`: The target node of the edge
+- `weight`: An optional numeric weight value for the edge
+
+The main operations of a graph data structure are:
+
+- `addNode`: Inserts a new node with the specific key and value
+- `addEdge`: Inserts a new edge between two given nodes, optionally setting its weight
+- `removeNode`: Removes the node with the specified key
+- `removeEdge`: Removes the edge between two given nodes
+- `findNode`: Retrieves the node with the given key
+- `hasEdge`: Checks if the graph has an edge between two given nodes
+- `setEdgeWeight`: Sets the weight of a given edge
+- `getEdgeWeight`: Gets the weight of a given edge
+- `adjacent`: Finds all nodes for which an edge exists from a given node
+- `indegree`: Calculates the total number of edges to a given node
+- `outdegree`: Calculates the total number of edges from a given node
+
+### Implementation
+
+```js
+class Graph {
+ constructor(directed = true) {
+ this.directed = directed;
+ this.nodes = [];
+ this.edges = new Map();
+ }
+
+ addNode(key, value = key) {
+ this.nodes.push({ key, value });
+ }
+
+ addEdge(a, b, weight) {
+ this.edges.set(JSON.stringify([a, b]), { a, b, weight });
+ if (!this.directed)
+ this.edges.set(JSON.stringify([b, a]), { a: b, b: a, weight });
+ }
+
+ removeNode(key) {
+ this.nodes = this.nodes.filter(n => n.key !== key);
+ [...this.edges.values()].forEach(({ a, b }) => {
+ if (a === key || b === key) this.edges.delete(JSON.stringify([a, b]));
+ });
+ }
+
+ removeEdge(a, b) {
+ this.edges.delete(JSON.stringify([a, b]));
+ if (!this.directed) this.edges.delete(JSON.stringify([b, a]));
+ }
+
+ findNode(key) {
+ return this.nodes.find(x => x.key === key);
+ }
+
+ hasEdge(a, b) {
+ return this.edges.has(JSON.stringify([a, b]));
+ }
+
+ setEdgeWeight(a, b, weight) {
+ this.edges.set(JSON.stringify([a, b]), { a, b, weight });
+ if (!this.directed)
+ this.edges.set(JSON.stringify([b, a]), { a: b, b: a, weight });
+ }
+
+ getEdgeWeight(a, b) {
+ return this.edges.get(JSON.stringify([a, b])).weight;
+ }
+
+ adjacent(key) {
+ return [...this.edges.values()].reduce((acc, { a, b }) => {
+ if (a === key) acc.push(b);
+ return acc;
+ }, []);
+ }
+
+ indegree(key) {
+ return [...this.edges.values()].reduce((acc, { a, b }) => {
+ if (b === key) acc++;
+ return acc;
+ }, 0);
+ }
+
+ outdegree(key) {
+ return [...this.edges.values()].reduce((acc, { a, b }) => {
+ if (a === key) acc++;
+ return acc;
+ }, 0);
+ }
+}
+```
+
+- Create a `class` with a `constructor` that initializes an empty array, `nodes`, and a `Map`, `edges`, for each instance. The optional argument, `directed`, specifies if the graph is directed or not.
+
+- Define an `addNode()` method, which uses `Array.prototype.push()` to add a new node in the `nodes` array.
+- Define an `addEdge()` method, which uses `Map.prototype.set()` to add a new edge to the `edges` Map, using `JSON.stringify()` to produce a unique key.
+- Define a `removeNode()` method, which uses `Array.prototype.filter()` and `Map.prototype.delete()` to remove the given node and any edges connected to it.
+- Define a `removeEdge()` method, which uses `Map.prototype.delete()` to remove the given edge.
+- Define a `findNode()` method, which uses `Array.prototype.find()` to return the given node, if any.
+- Define a `hasEdge()` method, which uses `Map.prototype.has()` and `JSON.stringify()` to check if the given edge exists in the `edges` Map.
+- Define a `setEdgeWeight()` method, which uses `Map.prototype.set()` to set the weight of the appropriate edge, whose key is produced by `JSON.stringify()`.
+- Define a `getEdgeWeight()` method, which uses `Map.prototype.get()` to get the eight of the appropriate edge, whose key is produced by `JSON.stringify()`.
+- Define an `adjacent()` method, which uses `Map.prototype.values()`, `Array.prototype.reduce()` and `Array.prototype.push()` to find all nodes connected to the given node.
+- Define an `indegree()` method, which uses `Map.prototype.values()` and `Array.prototype.reduce()` to count the number of edges to the given node.
+- Define an `outdegree()` method, which uses `Map.prototype.values()` and `Array.prototype.reduce()` to count the number of edges from the given node.
+
+```js
+const g = new Graph();
+
+g.addNode('a');
+g.addNode('b');
+g.addNode('c');
+g.addNode('d');
+
+g.addEdge('a', 'c');
+g.addEdge('b', 'c');
+g.addEdge('c', 'b');
+g.addEdge('d', 'a');
+
+g.nodes.map(x => x.value); // ['a', 'b', 'c', 'd']
+[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
+// ['a => c', 'b => c', 'c => b', 'd => a']
+
+g.adjacent('c'); // ['b']
+
+g.indegree('c'); // 2
+g.outdegree('c'); // 1
+
+g.hasEdge('d', 'a'); // true
+g.hasEdge('a', 'd'); // false
+
+g.removeEdge('c', 'b');
+
+[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
+// ['a => c', 'b => c', 'd => a']
+
+g.removeNode('c');
+
+g.nodes.map(x => x.value); // ['a', 'b', 'd']
+[...g.edges.values()].map(({ a, b }) => `${a} => ${b}`);
+// ['d => a']
+
+g.setEdgeWeight('d', 'a', 5);
+g.getEdgeWeight('d', 'a'); // 5
+```
diff --git a/articles/snippets/js-data-structures-linked-list.md b/articles/snippets/js-data-structures-linked-list.md
new file mode 100644
index 000000000..efe23b86d
--- /dev/null
+++ b/articles/snippets/js-data-structures-linked-list.md
@@ -0,0 +1,141 @@
+---
+title: JavaScript Data Structures - Linked List
+shortTitle: Linked List
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-3
+excerpt: A linked list is a linear data structure where each element points to the next.
+dateModified: 2021-08-08T05:00:00-04:00
+---
+
+### Definition
+
+A linked list is a linear data structure that represents a collection of elements, where each element points to the next one. The first element in the linked list is the head and the last element is the tail.
+
+
+
+Each element of a linked list data structure must have the following properties:
+
+- `value`: The value of the element
+- `next`: A pointer to the next element in the linked list (`null` if there is none)
+
+The main properties of a linked list data structure are:
+
+- `size`: The number of elements in the linked list
+- `head`: The first element in the linked list
+- `tail`: The last element in the linked list
+
+The main operations of a linked list data structure are:
+
+- `insertAt`: Inserts an element at the specific index
+- `removeAt`: Removes the element at the specific index
+- `getAt`: Retrieves the element at the specific index
+- `clear`: Empties the linked list
+- `reverse`: Reverses the order of elements in the linked list
+
+### Implementation
+
+```js
+class LinkedList {
+ constructor() {
+ this.nodes = [];
+ }
+
+ get size() {
+ return this.nodes.length;
+ }
+
+ get head() {
+ return this.size ? this.nodes[0] : null;
+ }
+
+ get tail() {
+ return this.size ? this.nodes[this.size - 1] : null;
+ }
+
+ insertAt(index, value) {
+ const previousNode = this.nodes[index - 1] || null;
+ const nextNode = this.nodes[index] || null;
+ const node = { value, next: nextNode };
+
+ if (previousNode) previousNode.next = node;
+ this.nodes.splice(index, 0, node);
+ }
+
+ insertFirst(value) {
+ this.insertAt(0, value);
+ }
+
+ insertLast(value) {
+ this.insertAt(this.size, value);
+ }
+
+ getAt(index) {
+ return this.nodes[index];
+ }
+
+ removeAt(index) {
+ const previousNode = this.nodes[index - 1];
+ const nextNode = this.nodes[index + 1] || null;
+
+ if (previousNode) previousNode.next = nextNode;
+
+ return this.nodes.splice(index, 1);
+ }
+
+ clear() {
+ this.nodes = [];
+ }
+
+ reverse() {
+ this.nodes = this.nodes.reduce(
+ (acc, { value }) => [{ value, next: acc[0] || null }, ...acc],
+ []
+ );
+ }
+
+ *[Symbol.iterator]() {
+ yield* this.nodes;
+ }
+}
+```
+
+- Create a `class` with a `constructor` that initializes an empty array, `nodes`, for each instance.
+- Define a `size` getter, that returns that uses `Array.prototype.length` to return the number of elements in the `nodes` array.
+- Define a `head` getter, that returns the first element of the `nodes` array or `null` if empty.
+- Define a `tail` getter, that returns the last element of the `nodes` array or `null` if empty.
+- Define an `insertAt()` method, which uses `Array.prototype.splice()` to add a new object in the `nodes` array, updating the `next` key of the previous element.
+- Define two convenience methods, `insertFirst()` and `insertLast()` that use the `insertAt()` method to insert a new element at the start or end of the `nodes` array respectively.
+- Define a `getAt()` method, which retrieves the element in the given `index`.
+- Define a `removeAt()` method, which uses `Array.prototype.splice()` to remove an object in the `nodes` array, updating the `next` key of the previous element.
+- Define a `clear()` method, which empties the `nodes` array.
+- Define a `reverse()` method, which uses `Array.prototype.reduce()` and the spread operator (`...`) to reverse the order of the `nodes` array, updating the `next` key of each element appropriately.
+- Define a generator method for `Symbol.iterator`, which delegates to the `nodes` array's iterator using the `yield*` syntax.
+
+```js
+const list = new LinkedList();
+
+list.insertFirst(1);
+list.insertFirst(2);
+list.insertFirst(3);
+list.insertLast(4);
+list.insertAt(3, 5);
+
+list.size; // 5
+list.head.value; // 3
+list.head.next.value; // 2
+list.tail.value; // 4
+[...list.map(e => e.value)]; // [3, 2, 1, 5, 4]
+
+list.removeAt(1); // 2
+list.getAt(1).value; // 1
+list.head.next.value; // 1
+[...list.map(e => e.value)]; // [3, 1, 5, 4]
+
+list.reverse();
+[...list.map(e => e.value)]; // [4, 5, 1, 3]
+
+list.clear();
+list.size; // 0
+```
diff --git a/articles/snippets/js-data-structures-queue.md b/articles/snippets/js-data-structures-queue.md
new file mode 100644
index 000000000..a54146a80
--- /dev/null
+++ b/articles/snippets/js-data-structures-queue.md
@@ -0,0 +1,75 @@
+---
+title: JavaScript Data Structures - Queue
+shortTitle: Queue
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-2
+excerpt: A queue is a linear data structure which follows a first in, first out (FIFO) order of operations.
+dateModified: 2021-07-29T05:00:00-04:00
+---
+
+### Definition
+
+A queue is a linear data structure that behaves like a real-world queue. It follows a first in, first out (FIFO) order of operations, similar to its real-world counterpart. This means that new items are added to the end of the queue, whereas items are removed from the start of the queue.
+
+
+
+The main operations of a queue data structure are:
+
+- `enqueue`: Adds an element to the end of the queue
+- `dequeue`: Removes an element from the start of the queue
+- `peek`: Retrieves the element at the start of the queue, without removing it
+- `isEmpty`: Checks if the queue is empty
+
+### Implementation
+
+```js
+class Queue {
+ constructor() {
+ this.items = [];
+ }
+
+ enqueue(item) {
+ this.items.push(item);
+ }
+
+ dequeue(item) {
+ return this.items.shift();
+ }
+
+ peek(item) {
+ return this.items[0];
+ }
+
+ isEmpty() {
+ return this.items.length === 0;
+ }
+}
+```
+
+- Create a `class` with a `constructor` that initializes an empty array, `items`, for each instance.
+- Define an `enqueue()` method, which uses `Array.prototype.push()` to add an element to the end of the `items` array.
+- Define a `dequeue()` method, which uses `Array.prototype.shift()` to remove an element from the start of the `items` array.
+- Define a `peek()` method, which retrieves the value of the first element in the `items` array, without removing it.
+- Define an `isEmpty()` method, which uses `Array.prototype.length` to determine if the `items` array is empty.
+
+```js
+const queue = new Queue();
+
+queue.isEmpty(); // true
+
+queue.enqueue('A');
+queue.enqueue('B');
+queue.enqueue('C');
+queue.enqueue('D');
+queue.enqueue('E');
+
+queue.isEmpty(); // false
+
+queue.peek(); // 'A'
+
+queue.dequeue(); // 'A'
+queue.dequeue(); // 'B'
+queue.dequeue(); // 'C'
+```
diff --git a/articles/snippets/js-data-structures-stack.md b/articles/snippets/js-data-structures-stack.md
new file mode 100644
index 000000000..aca725c98
--- /dev/null
+++ b/articles/snippets/js-data-structures-stack.md
@@ -0,0 +1,73 @@
+---
+title: JavaScript Data Structures - Stack
+shortTitle: Stack
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-1
+excerpt: A stack is a linear data structure which follows a last in, first out (LIFO) order of operations.
+dateModified: 2021-08-03T05:00:00-04:00
+---
+
+### Definition
+
+A stack is a linear data structure that behaves like a real-world stack of items. It follows a last in, first out (LIFO) order of operations, similar to its real-world counterpart. This means that new items are added to the top of the stack and items are removed from the top of the stack as well.
+
+
+
+The main operations of a stack data structure are:
+
+- `push`: Adds an element to the top of the stack
+- `pop`: Removes an element from the top of the stack
+- `peek`: Retrieves the element at the top of the stack, without removing it
+- `isEmpty`: Checks if the stack is empty
+
+### Implementation
+
+```js
+class Stack {
+ constructor() {
+ this.items = [];
+ }
+
+ push(item) {
+ this.items.unshift(item);
+ }
+
+ pop(item) {
+ return this.items.shift();
+ }
+
+ peek(item) {
+ return this.items[0];
+ }
+
+ isEmpty() {
+ return this.items.length === 0;
+ }
+}
+```
+
+- Create a `class` with a `constructor` that initializes an empty array, `items`, for each instance.
+- Define a `push()` method, which uses `Array.prototype.unshift()` to add an element to the start of the `items` array.
+- Define a `pop()` method, which uses `Array.prototype.shift()` to remove an element from the start of the `items` array.
+- Define a `peek()` method, which retrieves the value of the first element in the `items` array, without removing it.
+- Define an `isEmpty()` method, which uses `Array.prototype.length` to determine if the `items` array is empty.
+
+```js
+const stack = new Stack();
+
+stack.push('apples');
+stack.push('oranges');
+stack.push('pears');
+
+stack.isEmpty(); // false
+
+stack.peek(); // 'pears'
+
+stack.pop(); // 'pears'
+stack.pop(); // 'oranges'
+stack.pop(); // 'apples'
+
+stack.isEmpty(); // true
+```
diff --git a/articles/snippets/js-data-structures-tree.md b/articles/snippets/js-data-structures-tree.md
new file mode 100644
index 000000000..810944a4f
--- /dev/null
+++ b/articles/snippets/js-data-structures-tree.md
@@ -0,0 +1,137 @@
+---
+title: JavaScript Data Structures - Tree
+shortTitle: Tree
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: purple-flower-macro-2
+excerpt: A tree is a data structure consisting of a set of linked nodes representing a hierarchical tree structure.
+dateModified: 2021-08-22T05:00:00-04:00
+---
+
+### Definition
+
+A tree is a data structure consisting of a set of linked nodes that represent a hierarchical tree structure. Each node is linked to others via parent-children relationship. The first node in the tree is the root, whereas nodes without any children are the leaves.
+
+
+
+Each node in a tree data structure must have the following properties:
+
+- `key`: The key of the node
+- `value`: The value of the node
+- `parent`: The parent of the node (`null` if there is none)
+- `children`: An array of pointers to the node's children
+
+The main operations of a tree data structure are:
+
+- `insert`: Inserts a node as a child of the given parent node
+- `remove`: Removes a node and its children from the tree
+- `find`: Retrieves a given node
+- `preOrderTraversal`: Traverses the tree by recursively traversing each node followed by its children
+- `postOrderTraversal`: Traverses the tree by recursively traversing each node's children followed by the node
+
+### Implementation
+
+```js
+class TreeNode {
+ constructor(key, value = key, parent = null) {
+ this.key = key;
+ this.value = value;
+ this.parent = parent;
+ this.children = [];
+ }
+
+ get isLeaf() {
+ return this.children.length === 0;
+ }
+
+ get hasChildren() {
+ return !this.isLeaf;
+ }
+}
+
+class Tree {
+ constructor(key, value = key) {
+ this.root = new TreeNode(key, value);
+ }
+
+ *preOrderTraversal(node = this.root) {
+ yield node;
+ if (node.children.length) {
+ for (let child of node.children) {
+ yield* this.preOrderTraversal(child);
+ }
+ }
+ }
+
+ *postOrderTraversal(node = this.root) {
+ if (node.children.length) {
+ for (let child of node.children) {
+ yield* this.postOrderTraversal(child);
+ }
+ }
+ yield node;
+ }
+
+ insert(parentNodeKey, key, value = key) {
+ for (let node of this.preOrderTraversal()) {
+ if (node.key === parentNodeKey) {
+ node.children.push(new TreeNode(key, value, node));
+ return true;
+ }
+ }
+ return false;
+ }
+
+ remove(key) {
+ for (let node of this.preOrderTraversal()) {
+ const filtered = node.children.filter(c => c.key !== key);
+ if (filtered.length !== node.children.length) {
+ node.children = filtered;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ find(key) {
+ for (let node of this.preOrderTraversal()) {
+ if (node.key === key) return node;
+ }
+ return undefined;
+ }
+}
+```
+
+- Create a `class` for the `TreeNode` with a `constructor` that initializes the appropriate `key`, `value`, `parent` and `children` properties.
+- Define an `isLeaf` getter, that uses `Array.prototype.length` to check if `children` is empty.
+- Define a `hasChildren` getter, that is the reverse of the `isLeaf` getter.
+- Create a `class` for the `Tree` with a `constructor` that initializes the `root` of the tree.
+- Define a `preOrderTraversal()` generator method that traverses the tree in pre-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define a `postOrderTraversal()` generator method that traverses the tree in post-order, using the `yield*` syntax to recursively delegate traversal to itself.
+- Define an `insert()` method, that uses the `preOrderTraversal()` method and `Array.prototype.push()` to add a new `TreeNode` to the tree.
+- Define a `remove()` method, that uses the `preOrderTraversal()` method and `Array.prototype.filter()` to remove a `TreeNode` from the tree.
+- Define a `find()` method, that uses the `preOrderTraversal()` method to retrieve the given node in the tree.
+
+```js
+const tree = new Tree(1, 'AB');
+
+tree.insert(1, 11, 'AC');
+tree.insert(1, 12, 'BC');
+tree.insert(12, 121, 'BG');
+
+[...tree.preOrderTraversal()].map(x => x.value);
+// ['AB', 'AC', 'BC', 'BCG']
+
+tree.root.value; // 'AB'
+tree.root.hasChildren; // true
+
+tree.find(12).isLeaf; // false
+tree.find(121).isLeaf; // true
+tree.find(121).parent.value; // 'BC'
+
+tree.remove(12);
+
+[...tree.postOrderTraversal()].map(x => x.value);
+// ['AC', 'AB']
+```
diff --git a/articles/snippets/js-decimal-to-hex.md b/articles/snippets/js-decimal-to-hex.md
new file mode 100644
index 000000000..7d288f0f6
--- /dev/null
+++ b/articles/snippets/js-decimal-to-hex.md
@@ -0,0 +1,28 @@
+---
+title: "Tip: Convert decimal number to hexadecimal"
+shortTitle: Decimal to hexadecimal
+type: tip
+tags: [javascript,math]
+author: chalarangelo
+cover: waves-from-above
+excerpt: Ever needed to convert a decimal number to hexadecimal? Here's a quick and easy way to do it.
+dateModified: 2022-09-21T05:00:00-04:00
+---
+
+Numeric values are represented in decimal format by default, when converted to strings. If you want to display them in hexadecimal format, you can use `Number.prototype.toString()` and pass the base you want to use (`16`) as an argument.
+
+```js
+const decimalToHex = dec => dec.toString(16);
+
+decimalToHex(0); // '0'
+decimalToHex(255); // 'ff'
+```
+
+Conversely, the opposite might also be needed. You can use `parseInt()` to convert a string to a number in a given base. If you don't specify a base, it will default to `10`.
+
+```js
+const hexToDecimal = hex => parseInt(hex, 16);
+
+hexToDecimal('0'); // 0
+hexToDecimal('ff'); // 255
+```
diff --git a/articles/snippets/js-detect-undefined-object-property.md b/articles/snippets/js-detect-undefined-object-property.md
new file mode 100644
index 000000000..7adcb976e
--- /dev/null
+++ b/articles/snippets/js-detect-undefined-object-property.md
@@ -0,0 +1,33 @@
+---
+title: How can I detect an undefined object property in JavaScript?
+shortTitle: Detect undefined object property
+type: story
+tags: [javascript,object]
+author: chalarangelo
+cover: pink-flower
+excerpt: Learn how to detect `undefined` object properties in JavaScript the correct way.
+dateModified: 2022-08-07T05:00:00-04:00
+---
+
+It’s not uncommon to want to detect object properties with a value of `undefined`. While this seems straightforward on the surface, `undefined` is a rather elusive value to check for.
+
+More often than not solutions point towards direct strict comparison with `undefined` or using `typeof`. Both of these methods have a hard time differentiating between present properties with a value of `undefined` and non-existent properties. This, in turn, makes them prone to silent errors, shall you misspell the property altogether.
+
+```js
+const obj = { prop : undefined };
+obj.prop === undefined; // true
+typeof obj.prop === 'undefined'; // true
+obj.porp === undefined; // true
+typeof obj.porp === 'undefined'; // true
+```
+
+To alleviate the issue, `Object.prototype.hasOwnProperty()` can be used in addition to the previous method to check for the property actually being present on the object. Moreover, it can also be used for the opposite, so you can also detect non-existent properties and handle them accordingly.
+
+```js
+const hasUndefinedProperty = (obj, prop) =>
+ obj.hasOwnProperty(prop) && obj[prop] === undefined;
+
+const obj = { prop: undefined };
+hasUndefinedProperty(obj, 'prop'); // true
+hasUndefinedProperty(obj, 'porp'); // false
+```
diff --git a/articles/snippets/js-double-negation-operator.md b/articles/snippets/js-double-negation-operator.md
new file mode 100644
index 000000000..6defd297f
--- /dev/null
+++ b/articles/snippets/js-double-negation-operator.md
@@ -0,0 +1,36 @@
+---
+title: What does the double negation operator do in JavaScript?
+shortTitle: Double negation operator
+type: question
+tags: [javascript,type]
+author: chalarangelo
+cover: memories-of-pineapple-2
+excerpt: You've probably come across the double negation operator (`!!`) before, but do you know what it does?
+dateModified: 2022-07-26T05:00:00-04:00
+---
+
+JavaScript's negation operator (`!`) is a unary operator, used to invert the truth value of its operand. When used twice, known as the double negation operator (`!!`), it can be used to convert a value to a boolean.
+
+```js
+const x = 1;
+const y = null;
+
+!!x; // true
+!!y; // false
+```
+
+Using the double negation operator is functionally equivalent to using the `Boolean()` function, which we explored in depth in a [previous article](/articles/s/javascript-boolean-function). In terms of readability and usability, I would still suggest using the `Boolean()` function. It conveys the intent of the operation more clearly, and it's easier to understand at a glance.
+
+```js
+const x = 1;
+const y = null;
+
+Boolean(x); // true
+Boolean(y); // false
+
+const values = [0, 0, 2, 0, 3];
+// Kinda readable, but not great
+values.filter(x => !!x); // [2, 3]
+// Arguably more readable
+values.filter(Boolean); // [2, 3]
+```
diff --git a/articles/snippets/js-dynamic-getter-chain-proxy.md b/articles/snippets/js-dynamic-getter-chain-proxy.md
new file mode 100644
index 000000000..38f45578b
--- /dev/null
+++ b/articles/snippets/js-dynamic-getter-chain-proxy.md
@@ -0,0 +1,48 @@
+---
+title: Chaining dynamic getters using the Proxy object
+shortTitle: Dynamic getter chaining
+type: story
+tags: [javascript,object,proxy]
+author: chalarangelo
+cover: colorful-rocks
+excerpt: Using the Proxy object, we can create chainable dynamic getters for objects in JavaScript.
+dateModified: 2023-05-28T05:00:00-04:00
+---
+
+The dawn of ES6 brought about jQuery's fall from grace, as a lot of the conveniences it afforded developers were now available in the language itself. However, jQuery's API design was convenient in many ways that native JavaScript often isn't. One of the most practical things jQuery offered was its ability to chain methods together, minimizing duplication and making code more readable.
+
+Looking at the use case at hand, I thought that I could stitch together a general-purpose solution using JavaScript's `Proxy` object. In fact, I think that the concept of dynamic getters and setters that I described in [my previous post](/articles/s/js-dynamic-getter-setter-proxy) is a great place to start.
+
+To recap, intercepting the behavior of the `get` and `set` traps of a `Proxy` object allows us to create dynamic accessors for objects. This is particularly useful when the shape of the data is not known in advance, or when the value of a property needs to be manipulated before it is returned.
+
+In our scenario, we want each property to be accessed as a function. The function should do one of two things, depending on the argument it receives:
+
+- If the argument is `undefined`, then the property should be returned as-is.
+- If the argument is any other value, the property should be set to the value of the argument and a proxy of the object should be returned.
+
+Given these requirements, we can define the handler's behavior for the `get` trap. All we need to do is check if the argument is `undefined` and choose which behavior to perform. Here's what the code looks like:
+
+```js
+const getHandler = {
+ get: (target, prop) => {
+ return value => {
+ if (typeof value !== 'undefined') {
+ target[prop] = value;
+ return new Proxy(target, getHandler);
+ }
+ return target[prop];
+ };
+ }
+};
+
+const styles = {};
+const proxiedStyles = new Proxy(styles, getHandler);
+
+proxiedStyles.color('#101010').background('#fefefe').margin('4px 8px');
+
+proxiedStyles.color(); // #101010
+proxiedStyles.background(); // #fefefe
+proxiedStyles.margin(); // 4px 8px
+```
+
+As you can see the handler is pretty short and straightforward. The only confusing step is the creation of a new `Proxy` inside the trap. As we don't have a reference to the proxy object itself inside the trap, we need to create a new one. This is necessary because we want to return a new proxy to allow for chaining. If we didn't do this, the proxy would only be able to be used once.
diff --git a/articles/snippets/js-dynamic-getter-setter-proxy.md b/articles/snippets/js-dynamic-getter-setter-proxy.md
new file mode 100644
index 000000000..4f8e78fb9
--- /dev/null
+++ b/articles/snippets/js-dynamic-getter-setter-proxy.md
@@ -0,0 +1,75 @@
+---
+title: Can I create dynamic setters and getters in JavaScript?
+shortTitle: Dynamic getters and setters
+type: question
+tags: [javascript,object,proxy]
+author: chalarangelo
+cover: green-cabin-cow
+excerpt: Using the Proxy object, we can create dynamic getters and setters for objects in JavaScript.
+dateModified: 2023-04-09T05:00:00-04:00
+---
+
+Sometimes, when working with objects, the shape of the data is not always known. It might also be inefficient to add special getters for each property of an object, especially if the object is very large. Moreover, if keys are expected to follow a pattern, there are infinite potential key names, the value of which is impossible to validate via the use of setters.
+
+These are only some use-cases where **dynamic setters and getters** could be useful. Luckily, JavaScript's `Proxy` object can be used for this purpose. Using the `get` and `set` traps, we can manipulate the object's behavior when a property is accessed or set. In this post, we will look at two simple examples to give you an idea of how this works.
+
+Note that, in contrast to these examples, a `Proxy` object can define multiple traps to intercept many different operations on the target object.
+
+### Dynamic getters
+
+A **dynamic getter** is a getter that is not explicitly defined for a property, but is instead created on the fly when the property is accessed. This is particularly useful when the shape of the data is not known in advance, or when the value of a property needs to be manipulated before it is returned.
+
+In this example, we will be creating a proxy that will manipulate string values in the target object. The proxy will trim any string values that are accessed, and return the value as-is for any other type of value. Finally, non-existent properties will return `undefined`, as expected.
+
+```js
+const obj = { foo: 'bar ', baz: ' qux ', quux: 1 };
+
+const proxiedObj = new Proxy(obj, {
+ get(target, prop) {
+ if (prop in target && typeof target[prop] === 'string')
+ return target[prop].trim();
+ return target[prop];
+ }
+});
+
+proxiedObj.foo; // 'bar'
+proxiedObj.baz; // 'qux'
+proxiedObj.quux; // 1
+proxiedObj.quuz; // undefined
+```
+
+While this is a simple example, it highlights the power of the `Proxy` object. In this case, we are able to manipulate the behavior of the object without having to define a getter for each property. This will also apply to any new properties that are added to the object, as the proxy will be able to intercept the access and return the appropriate value.
+
+### Dynamic setters
+
+A **dynamic setter** is a setter that is not explicitly defined for a property, but is instead created on the fly when the property is set. This can be very useful if the object's keys follow a certain pattern or certain conditions apply to all values that are set.
+
+In this example, we will be creating a proxy that will only allow setting of properties that correspond to a date in the format `yyyy-mm-dd`. Additionally, if a property is already set, its value should be impossible to change. This could be useful if, for example, you were creating something akin to a read-only log.
+
+```js
+const obj = {};
+
+const proxiedObj = new Proxy(obj, {
+ set(target, prop, value) {
+ if (prop in target) return false;
+ if (typeof prop === 'string' && prop.match(/^\d{4}-\d{2}-\d{2}$/)) {
+ target[prop] = value;
+ return true;
+ }
+ return false;
+ }
+});
+
+proxiedObj['2023-01-01'] = 1;
+proxiedObj['2023-01-01'] = 2; // This will fail, the property is already set
+proxiedObj['2023-ab-cd'] = 1; // This will fail, the property name is not a date
+proxiedObj; // { '2023-01-01': 1 }
+```
+
+As shown in this example, the `Proxy` object can be used to validate keys as well as values when setting properties. In this case, we were able to prevent the value of a property from being changed, as well as prevent the setting of properties that do not follow the expected pattern.
+
+As a side note, remember that the regular expression used here is not a full date validation, but only checks for a simple pattern to demonstrate the concept. If you need to validate dates in a production environment, this is not the way to go.
+
+### Conclusion
+
+As shown in this post, the `Proxy` object provides a particularly powerful way to manipulate the behavior of objects. That being said, you might want to consider your specific use-case before reaching for this tool. Dynamic getters and setters can be very useful, but they can also cause a lot of headaches if used incorrectly.
diff --git a/articles/snippets/js-dynamic-properties-are-slow.md b/articles/snippets/js-dynamic-properties-are-slow.md
new file mode 100644
index 000000000..9470895bb
--- /dev/null
+++ b/articles/snippets/js-dynamic-properties-are-slow.md
@@ -0,0 +1,36 @@
+---
+title: "Tip: Optimize dynamically added object properties"
+shortTitle: Dynamically added property optimization
+type: tip
+tags: [javascript,object,performance]
+author: chalarangelo
+cover: mountain-lake-cottage
+excerpt: Dynamically adding object properties can be pretty slow in some cases. Here's how to optimize it.
+dateModified: 2022-11-02T05:00:00-04:00
+---
+
+JavaScript is one of the most flexible languages out there, but sometimes this comes with performance costs attached. One such example is the use of dynamically added properties to objects. Oddly enough, this performance impact comes from JavaScript engines optimizing for static typing.
+
+The V8 engine, which powers Chrome and Node.js, uses **shapes** and **transition chains** to optimize object property access. When two objects have the same properties, they are considered to have the same shape. Adding new properties to an object, creates a transition chain to add the new property. Without getting into further detail, it's obvious that a simple shape is faster to access than a transition chain.
+
+```js
+// Create an object with a single property
+const obj = { a: 1 };
+// Add a new property to the object
+obj.b = 2;
+// Access a property of the object
+console.log(obj.a);
+```
+
+Circling back to dynamically added properties, the engine cannot know ahead of time what properties will be added to the object. Thus, it ends up creating a transition chain for each new property that is added. This is not a big deal for a few properties, but it can become a problem when adding a lot of properties to an object.
+
+Luckily, this is easy to fix. The easiest solution is to **define all possible properties of an object ahead of time** and give them an empty value (i.e. `null` or `undefined`). This way, the engine can create a shape for the object and optimize property access. This is not always possible, but it's a good practice to follow.
+
+```js
+// Create an object with all possible properties
+const obj = { a: 1, b: undefined };
+// Add a new property to the object
+obj.b = 2;
+// Access a property of the object
+console.log(obj.a);
+```
diff --git a/articles/snippets/js-edit-url-params.md b/articles/snippets/js-edit-url-params.md
new file mode 100644
index 000000000..fbdbfd34c
--- /dev/null
+++ b/articles/snippets/js-edit-url-params.md
@@ -0,0 +1,40 @@
+---
+title: "Tip: Edit URL Parameters in JavaScript"
+shortTitle: Edit URL Parameters
+type: tip
+tags: [javascript,string]
+author: chalarangelo
+cover: sofia-tram
+excerpt: Avoid the naive approach and use a more robust method to edit URL parameters in JavaScript.
+dateModified: 2022-12-07T05:00:00-04:00
+---
+
+Editing the query string of a URL in JavaScript is pretty common. While the naive approach of directly editing the URL as a string often works, it's a fragile solution that can break easily. This is especially true when working with encoding, hash fragments and other such intricacies.
+
+The most robust way to go about editing a URL is using the `URL` interface to parse the original URL string and edit it as necessary. This way, the browser will take care of all the complicated details and make the code easier to read and maintain.
+
+```js
+const urlString = 'https://mysite.com?p=42&from=home#details';
+const url = new URL(urlString);
+
+// Delete a parameter
+const removedParam = 'from';
+url.searchParams.delete(removedParam);
+
+// Edit/add parameters
+const newParams = {
+ p: 57,
+ track: 'none'
+};
+Object.keys(newParams).forEach(key => {
+ url.searchParams.set(key, newParams[key]);
+});
+
+// Edit the hash fragment
+const newHash = 'new';
+url.hash = newHash;
+
+console.log(`${url}`); // https://mysite.com?p=57&track=none#new
+```
+
+As you can see in the example, the `URL` interface provides a number of methods to edit the URL. The most commonly used ones are `URL.searchParams` and `URL.hash`. The former is a `URLSearchParams` object that provides methods to edit the query string of the URL, while the latter is a string that contains the hash fragment of the URL. Apart from these two, the `URL` interface also provides methods to edit the protocol, host, port, path, etc. of the URL.
diff --git a/articles/snippets/js-element-from-point.md b/articles/snippets/js-element-from-point.md
new file mode 100644
index 000000000..5e119e4cf
--- /dev/null
+++ b/articles/snippets/js-element-from-point.md
@@ -0,0 +1,22 @@
+---
+title: "Tip: Element at a specific point on the page"
+shortTitle: Element at specific coordinates
+type: tip
+tags: [javascript,browser]
+author: chalarangelo
+cover: armchair-in-yellow
+excerpt: Using `Document.elementFromPoint()` to easily get the element at a specific point on the page.
+dateModified: 2022-12-18T05:00:00-04:00
+---
+
+Figuring out where an element is located on the page with JavaScript can be tricky. Such needs often arise when working with pointer events or other forms of user input. As expected, such a common problem has many different viable solutions using well-established web APIs.
+
+As I recently discovered, `Document.elementFromPoint()` provides a pretty interesting and straightforward solution. It allows you to get the element at a specific point on the page and it also works quite well with `iframe`s, too. Additionally, `Document.elementsFromPoint()` provides similar functionality, but returns an array of all the elements at a specific point on the page, in order of their z-index.
+
+```js
+// Returns the topmost element at the specified coordinates
+const element = document.elementFromPoint(x, y);
+
+// Returns an array of all the elements at the specified coordinates
+const elements = document.elementsFromPoint(x, y);
+```
diff --git a/articles/snippets/js-email-validation.md b/articles/snippets/js-email-validation.md
new file mode 100644
index 000000000..ab8455fc6
--- /dev/null
+++ b/articles/snippets/js-email-validation.md
@@ -0,0 +1,41 @@
+---
+title: Can I validate an email address in JavaScript?
+shortTitle: Email address validation
+type: question
+tags: [javascript,string,regexp]
+author: chalarangelo
+cover: blank-card
+excerpt: Email address validation can be much trickier than it sounds. Here's why and my advice on how to approach this problem.
+dateModified: 2022-10-05T05:00:00-04:00
+---
+
+One of the most frequent code snippet requests I get is about a function that can validate email addresses. While it sounds easy, I’ve been putting off writing about this topic for a while. The reason is that there are **no great solutions to this sort of problem**.
+
+Theoretically, email addresses can be validated using a regular expression. After all, there are a couple of simple rules, such as the presence of the at (`@`) symbol and an appropriate domain, right? Yes, but there are tons of valid email address that don’t look exactly like that. In fact, there’s a whole standard, [RFC 2822](https://www.rfc-editor.org/rfc/rfc2822#section-3.4.1), that defines what email addresses can look like. Then, there’s the issue of what different mail servers will allow. Gmail, for example, will not allow underscores (`_`) or more than one period (`.`) in a row.
+
+Additionally, even if you could validate an email address, there’s **no way of knowing if this address is in fact currently in use**. The only way to do so, is to send an email and check the response. This is why most websites and apps nowadays send you a confirmation email in the first place.
+
+Finally, even if you used a regular expression that is compliant with RFC 2822, it wouldn’t be without issues. Understanding how it works or figuring out if it works correctly for each and every case would be pretty difficult. More importantly, though, it could be prone to **regular expression denial of service (ReDoS) attacks**, if implemented incorrectly.
+
+By now, you should be starting to figure out why I’ve been hesitant to showcase a solution to the problem of email validation. While solutions do exist, the implications of each one must be considered carefully.
+
+My suggestion would be to **check for basic structural elements** on the frontend, then **send a confirmation email** from your server to check that the email address is in use. It’s easy to implement and gets the job done. Going back to the original idea, here’s a simple function that checks for the most common syntax errors.
+
+```js
+const isEmailValid = address => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(address);
+
+isEmailValid('abcd@site.com'); // true
+isEmailValid('ab_c@site.com'); // true
+isEmailValid('ab.c@site.com'); // true
+isEmailValid('a@my.site.com'); // true
+isEmailValid('ab c@site.com'); // false
+isEmailValid('ab@c@site.com'); // false
+isEmailValid('abcde@sitecom'); // false
+isEmailValid('abcdesite.com'); // false
+```
+
+This regular expression is pretty short, yet it validates the following conditions:
+
+- No whitespace characters anywhere in the email address
+- Presence of a single at (`@`) character before the domain part
+- At least one dot (`.`) character in the domain part
diff --git a/articles/snippets/js-fast-remove-array-element.md b/articles/snippets/js-fast-remove-array-element.md
new file mode 100644
index 000000000..14bb9d8d3
--- /dev/null
+++ b/articles/snippets/js-fast-remove-array-element.md
@@ -0,0 +1,25 @@
+---
+title: Faster element removal in unordered JavaScript arrays
+shortTitle: Faster element removal in unordered arrays
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: purple-flower-bunch
+excerpt: Are you performing a lot of array operations? Maybe element removal is a performance bottleneck you can avoid.
+dateModified: 2022-03-20T05:00:00-04:00
+---
+
+`Array.prototype.splice()` is the most commonly-used way to remove elements from an array. Turns out that it’s not the fastest, though. This can be an especially important factor contributing to your code’s performance, if you are performing many operations with large arrays.
+
+There’s a pretty easy trick that you can use to speed up this operation, but the order of elements in the array must not play a role for it to work. Provided the latter is true, you can swap two elements in the array without any issues. This means you can swap any element with the last one, for example. But removing the last element is easy and fast, using `Array.prototype.pop()`, so you can use that to your advantage. For example:
+
+```js
+const arr = [3, 1, 5, 7, 9]; // Want to remove 5 (index: 2)
+
+arr[2] = arr[arr.length -1]; // Copy last element to 3rd place
+arr.pop(); // Remove the last element
+```
+
+In this example, we want to remove an element which is in the middle of the array. We would start by performing a swap of the element we want to remove with the last one. However, we don’t need to actually swap them. All we need to do is ensure that the last element goes in the place of the one we want to remove. We can simply copy it to that position and then use `Array.prototype.pop()` to remove the last element.
+
+On a side note, one could think shortening this to `arr[i] = arr.pop()` would make it even terser. Turns out this isn’t the case, as this shorter version will fail if we try to remove the last element in the array.
diff --git a/articles/snippets/js-frequency-map-data-structure.md b/articles/snippets/js-frequency-map-data-structure.md
new file mode 100644
index 000000000..227a13ccc
--- /dev/null
+++ b/articles/snippets/js-frequency-map-data-structure.md
@@ -0,0 +1,60 @@
+---
+title: Frequency Map Data Structure
+shortTitle: Frequency Map
+type: story
+tags: [javascript,class]
+author: chalarangelo
+cover: radio-monstera
+excerpt: A custom data structure to keep track of value frequencies in an array.
+dateModified: 2022-11-13T05:00:00-04:00
+---
+
+Counting the frequency of unique values in an array is reasonably easy, as demonstrated in the [frequencies snippet](/js/s/frequencies). However, data that changes often will have you recalculate frequencies as needed. This can become tedious and inefficient, especially if you only need to keep track of the frequencies and have no need for the original array.
+
+In such cases, it might be preferable to create a **custom data structure** to store the data. This data structure will be able to **keep track of the frequencies of the values** it contains and update them as needed. Here's how you can implement such a data structure:
+
+```js
+class FrequencyMap extends Map {
+ constructor(iterable) {
+ super();
+ iterable.forEach(value => this.add(value));
+ }
+
+ set() {
+ throw new Error('Please use Map.prototype.add() instead.');
+ }
+
+ add(value) {
+ if (this.has(value)) super.set(value, this.get(value) + 1);
+ else super.set(value, 1);
+ return this;
+ }
+
+ delete(value) {
+ if (this.get(value) === 1) super.delete(value);
+ else super.set(value, this.get(value) - 1);
+ return this;
+ }
+
+ sorted(ascending = true) {
+ if (ascending) return [...this].sort((a, b) => a[1] - b[1]).map(v => v[0]);
+ else return [...this].sort((a, b) => b[1] - (1)[1]).map(v => v[0]);
+ }
+}
+```
+
+- Leverage the built-in `Map` class via the use of inheritance.
+- Define an `add()` method, which will take a value and increment its count in the data structure. Use `Map.prototype.has()` to check if the value already exists and act accordingly.
+- Extend `Map.prototype.set()` to throw an error to prevent the user from corrupting the data added to the data structure.
+- Extend `Map.prototype.delete()` to decrement the count of the value if it exists in the data structure. Use `Map.prototype.has()` to check if the value's frequency is `1` and delete it if necessary.
+- As the data structure operates more like a `Set`, after the `constructor` to accept an array of values. Use `Array.prototype.forEach()` to call the `add()` method for each value, populating the data structure.
+- Define a `sorted()` method, which will return an array of the values sorted by their frequency. Use `Array.prototype.sort()` to sort the values by their frequency and `Array.prototype.map()` to return only the values. The `ascending` argument determines the order of the returned array.
+
+```js
+const fMap = new FrequencyMap(['a', 'b', 'c', 'a', 'a', 'b']);
+
+fMap.delete('c');
+fMap.add('d');
+
+console.log(fMap.sorted(false)); // [ 'a', 'b' , 'd' ]
+```
diff --git a/articles/snippets/js-immutable-object-proxy.md b/articles/snippets/js-immutable-object-proxy.md
new file mode 100644
index 000000000..7c24cb8e3
--- /dev/null
+++ b/articles/snippets/js-immutable-object-proxy.md
@@ -0,0 +1,45 @@
+---
+title: Immutable JavaScript objects using the Proxy object
+shortTitle: Immutable objects using Proxy
+type: story
+tags: [javascript,object,proxy]
+author: chalarangelo
+cover: frozen-globe
+excerpt: Freezing objects is not the only way to prevent mutations. Learn how you can leverage the Proxy object to your advantage.
+dateModified: 2022-04-10T05:00:00-04:00
+---
+
+Object mutability and its relation to the `const` keyword is a very common headache for developers. More often than not, when looking for ways to make an object immutable, `Object.freeze()` will pop up as a solution. We’ve explored this approach previously, elaborating on deep freezing solutions. You can read more about it in [this article](/articles/s/javascript-deep-freeze-object).
+
+While `Object.freeze()` is the more straightforward approach, it might not always be the best solution. This may be especially true when dealing with extensive object nesting or when objects have a very short life. For such cases, a different approach using the [Proxy object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) might make more sense. Here’s what that looks like:
+
+```js
+const term = {
+ id: 1,
+ value: 'hello',
+ properties: [{ type: 'usage', value: 'greeting' }],
+};
+
+const immutable = obj =>
+ new Proxy(obj, {
+ get(target, prop) {
+ return typeof target[prop] === 'object'
+ ? immutable(target[prop])
+ : target[prop];
+ },
+ set() {
+ throw new Error('This object is immutable.');
+ },
+ });
+
+const immutableTerm = immutable(term);
+const immutableProperty = immutableTerm.properties[0];
+
+immutableTerm.name = 'hi'; // Error: This object is immutable.
+immutableTerm.id = 2; // Error: This object is immutable.
+immutableProperty.value = 'pronoun'; // Error: This object is immutable.
+```
+
+Even though proxies are not all that common, this code shouldn’t be hard to understand. The gist of the idea is that you use a handler to prevent mutations to the object via the `set()` trap. Additionally, you use the `get()` trap to enforce immutability on all nested values. This is done by checking the type of the value and applying the proxy to nested objects.
+
+That’s pretty much all there is to it. With just a few lines of code, you now have a way to prevent mutation on an object, regardless of shape, nesting or complexity.
diff --git a/articles/snippets/js-last-element-of-array.md b/articles/snippets/js-last-element-of-array.md
new file mode 100644
index 000000000..76ada793b
--- /dev/null
+++ b/articles/snippets/js-last-element-of-array.md
@@ -0,0 +1,24 @@
+---
+title: "Tip: Get the last element of a JavaScript array"
+shortTitle: Last element of array
+type: tip
+tags: [javascript,array]
+author: chalarangelo
+cover: purple-laptop
+excerpt: Array destructuring can be leveraged in many different ways. Here's one of them.
+dateModified: 2022-08-28T05:00:00-04:00
+---
+
+If you have worked with JavaScript arrays before, you might know that they can be destructured much like objects. This is most commonly used to extract the first value of an array or the values of an array with a known length.
+
+But destructuring can go much further, as it allows you to extract the `length` property of an array. Add this to the fact that extracted variables can be used in the destructuring assignment itself and you can put together a one-liner to extract the last element of an array.
+
+```js
+const arr = [1, 2, 3];
+const { 0: first, length, [length - 1]: last } = arr;
+first; // 1
+last; // 3
+length; // 3
+```
+
+While this technique is interesting, it has a couple of caveats. First off, you have to extract the `length` property, which creates an additional variable for it. And secondly, it doesn't have any significant performance advantages over other options, such as using `Array.prototype.slice()`.
diff --git a/articles/snippets/js-locale-sensitive-string-truncation.md b/articles/snippets/js-locale-sensitive-string-truncation.md
new file mode 100644
index 000000000..7962830de
--- /dev/null
+++ b/articles/snippets/js-locale-sensitive-string-truncation.md
@@ -0,0 +1,48 @@
+---
+title: How can I truncate a string accounting for locale?
+shortTitle: Locale-sensitive string truncation
+type: question
+tags: [javascript,string]
+author: chalarangelo
+cover: reflection-on-lake
+excerpt: Locale-sensitive string splitting and truncation are finally possible in JavaScript.
+dateModified: 2022-12-04T05:00:00-04:00
+---
+
+Breaking a string into words is not the easiest, neither is finding a good place to add an ellipsis. Part of the problem is recognizing word boundaries and words themselves. Luckily `Intl.Segmenter` is a relatively new object that enables **locale-sensitive text segmentation**.
+
+`Intl.Segmenter` allows you to specify a locale and a `granularity` option to specify how a string should be segmented. The `granularity` option can be set to `'grapheme'`, `'word'` or `'sentence'` according to your needs. Using `Intl.Segmenter.prototype.segment()` on a string returns an iterable `Segments` object. This can then be used to find the correct index to split a string without being in the middle of a word or a sentence.
+
+```js
+const str =
+ 'The quick brown fox jumps over the lazy dog. The jay, pig, fox, zebra and my wolves quack!';
+const cutOff = 50;
+
+const wordSegmenter = new Intl.Segmenter('en-US', { granularity: 'word' });
+const sentenceSegmenter = new Intl.Segmenter('en-US', {
+ granularity: 'sentence',
+});
+
+let lastWordBreak = -1;
+for (let word of wordSegmenter.segment(str)) {
+ if (word.isWordLike) continue;
+ if (word.index >= cutOff) break;
+ lastWordBreak = word.index;
+}
+str.slice(0, lastWordBreak) + '...';
+// 'The quick brown fox jumps over the lazy dog. The...'
+
+let lastSentenceBreak = -1;
+for (let sentence of sentenceSegmenter.segment(str)) {
+ if (
+ lastSentenceBreak !== -1 &&
+ sentence.index + sentence.segment.length >= cutOff
+ )
+ break;
+ lastSentenceBreak = sentence.index + sentence.segment.length;
+}
+str.slice(0, lastSentenceBreak).trim().slice(0, -1) + '...';
+// 'The quick brown fox jumps over the lazy dog...'
+```
+
+Note that the `Intl.Segmenter` object is not yet supported in all environments at the time of writing (December, 2022). Namely, Firefox has yet to implement it, while Node.js has only started supporting it since version 16.0.0.
diff --git a/articles/snippets/js-map-vs-object.md b/articles/snippets/js-map-vs-object.md
new file mode 100644
index 000000000..da0a00236
--- /dev/null
+++ b/articles/snippets/js-map-vs-object.md
@@ -0,0 +1,68 @@
+---
+title: What are the differences between Maps and objects in JavaScript?
+shortTitle: Maps vs objects
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: tent-stars
+excerpt: Maps and objects are very similar, but they have some differences that can help you decide which one better fits your use-case.
+dateModified: 2022-02-13T05:00:00-04:00
+---
+
+Most JavaScript developers are familiar with objects and probably use them every day. Maps, on the other hand, are not as common but are still very useful. While very similar to objects on the surface, they have some very important differences. Let's take a look at them.
+
+### Key types
+
+Object keys are limited to using only strings and symbols. Maps, on the other hand, can use values of any type as their keys, including functions and objects. This can come in handy in many different scenarios, such as memoization and data association.
+
+```js
+const people = [
+ { id: 1, name: 'John', surname: 'Doe', age: 30 },
+ { id: 2, name: 'Jane', surname: 'Doe', age: 28 },
+];
+
+const peopleIndex = people.reduce((index, person) => {
+ index[person.id] = `${person.name} ${person.surname}`;
+ return index;
+}, {});
+// peopleIndex = {
+// '1': 'John Doe',
+// '2': 'Jane Doe',
+// }
+
+const peopleIndexMap = new Map(
+ people.map(person => [person, `${person.name} ${person.surname}`])
+);
+
+// peopleIndexMap = Map {
+// { id: 1, name: 'John', surname: 'Doe', age: 30 } => 'John Doe',
+// { id: 2, name: 'Jane', surname: 'Doe', age: 28 } => 'Jane Doe',
+// }
+```
+
+### Iteration
+
+Object iteration is usually accomplished using `Object.keys()`, `Object.values()` or `Object.entries()`. All of these methods are available on Maps as part of their prototype, but they are significantly more efficient. The reason for this is that these Map methods return iterators, which are lazy and only iterate over the keys or values when they are needed. Additionally, Maps expose an iterator, which can be used with `for...of` loops.
+
+```js
+const obj = { a: 1, b: 2, c: 3 };
+const objEntries = Object.entries(obj);
+// ['a', 1], ['b', 2], ['c', 3]
+for (const [key, value] of objEntries)
+ console.log(`${key}: ${value}`);
+
+const map = new Map([['a', 1], ['b', 2], ['c', 3]]);
+const mapEntries = [...map.entries()]; // Same as [...map]
+// [['a', 1], ['b', 2], ['c', 3]]
+for (const [key, value] of map)
+ console.log(`${key} => ${value}`);
+```
+
+### Other differences
+
+Apart from the two main differences mentioned already, there are some other, less noticeable, ones. These include the following:
+
+- Object size requires manual computation. Maps, on the other hand, have a built-in `size` property that can be used to track the number of key-value pairs.
+- You can check for a given key's presence in an object using the `in` operator or `Object.prototype.hasOwnProperty()`. `Map.prototype.has()` accomplishes the same thing for Maps.
+- Clearing an object requires manual operation and might be non-trivial in some cases. Maps solve this problem via the use of `Map.prototype.clear()`.
+- Objects inherit some keys from the prototype, whereas maps do not.
diff --git a/articles/snippets/js-native-data-structures.md b/articles/snippets/js-native-data-structures.md
new file mode 100644
index 000000000..fe71fb9c7
--- /dev/null
+++ b/articles/snippets/js-native-data-structures.md
@@ -0,0 +1,87 @@
+---
+title: Native JavaScript Data Structures
+shortTitle: Native Data Structures
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: purple-flower-macro-2
+excerpt: JavaScript provides a handful of native data structures that you can start using in your code right now.
+dateModified: 2021-09-05T05:00:00-04:00
+---
+
+### Arrays
+
+An array is a linear data structure that represents a collection of elements. In JavaScript, arrays don't have a fixed size, while their contents can be of any valid type, even arrays themselves. Arrays are probably the most commonly used data structure and come with a plethora of methods that allow easy manipulation and transformation of their contents.
+
+```js
+const nums = [1, 2, 3];
+const strs = Array.from('est');
+
+nums.push(6);
+nums.push(4, 9);
+strs.unshift('t');
+
+nums.length; // 6
+nums[nums.length - 1]; // 9
+strs[0]; // 't'
+strs[2]; // 's'
+
+nums.slice(1, 3); // [2, 3]
+nums.map(n => n * 2); // [2, 4, 6, 12, 8, 18]
+nums.filter(n => n % 2 === 0); // [2, 6, 4]
+nums.reduce((a, n) => a + n, 0); // 25
+
+strs.reverse(); // ['t', 's', 'e', 't']
+strs.join(''); // 'test'
+```
+
+### Sets
+
+A set is a linear data structure that represents an ordered collection of unique values. Sets in JavaScript can store any valid type of value, however each value can only occur once based on value equality checking.
+
+```js
+const nums = new Set([1, 2, 3]);
+
+nums.add(4);
+nums.add(1);
+nums.add(5);
+nums.add(4);
+
+nums.size; // 5
+nums.has(4); // true
+
+nums.delete(4);
+nums.has(4); // false
+
+[...nums]; // [1, 2, 3, 5]
+
+nums.clear();
+nums.size; // 0
+```
+
+### Maps
+
+A map is an associative data structure that represents a keyed collection of elements. Each key in a JavaScript Map has to be unique and either a primitive value or an object, whereas the values of the map can be of any valid type.
+
+```js
+const items = new Map([
+ [1, { name: 'John' }],
+ [2, { name: 'Mary' }]
+]);
+
+items.set(4, { name: 'Alan' });
+items.set(2, { name: 'Jeff' });
+
+items.size; // 3
+items.has(4); // true
+items.get(2); // { name: 'Jeff' }
+
+items.delete(2);
+items.size; // 2
+
+[...items.keys()]; // [1, 4]
+[...items.values()]; // [{ name: 'John' }, { name: 'Alan' }]
+
+items.clear();
+items.size; // 0
+```
diff --git a/articles/snippets/js-object-freeze-vs-seal.md b/articles/snippets/js-object-freeze-vs-seal.md
new file mode 100644
index 000000000..034c068fa
--- /dev/null
+++ b/articles/snippets/js-object-freeze-vs-seal.md
@@ -0,0 +1,35 @@
+---
+title: What is the difference between Object.freeze() and Object.seal() in JavaScript?
+shortTitle: Object.freeze() vs Object.seal()
+type: question
+tags: [javascript,object]
+author: chalarangelo
+cover: frozen-globe
+excerpt: Both `Object.freeze()` and `Object.seal()` serve a similar purpose, but there's one key difference you need to remember.
+dateModified: 2022-02-06T05:00:00-04:00
+---
+
+Both `Object.freeze()` and `Object.seal()` serve as ways to prevent a JavaScript object from being altered. Although similar, they have a key difference that you need to remember.
+
+```js
+const frozen = Object.freeze({ username: 'johnsmith' });
+const sealed = Object.seal({ username: 'johnsmith' });
+
+frozen.name = 'John Smith'; // frozen = { username: 'johnsmith' }
+sealed.name = 'John Smith'; // sealed = { username: 'johnsmith' }
+
+delete frozen.username; // frozen = { username: 'johnsmith' }
+delete sealed.username; // sealed = { username: 'johnsmith' }
+
+frozen.username = 'jsmith'; // frozen = { username: 'johnsmith' }
+sealed.username = 'jsmith'; // sealed = { username: 'jsmith' }
+```
+
+If you want to prevent new properties from being added and existing properties from being removed, then both methods will suit your needs. If, however, you want to prevent existing properties from being altered, then you have to use `Object.freeze()`. The reason for that is that `Object.seal()` only marks existing properties as non-configurable, meaning their values can be changed as long as they are writable.
+
+| | Create | Read | Update | Delete |
+| --- | --- | --- | --- | --- |
+| `Object.freeze()` | No | Yes | No | No |
+| `Object.seal()` | No | Yes | Yes | No |
+
+As a closing note, remember that both methods perform a shallow freeze/seal on the object. This means that nested objects and arrays are not frozen or sealed and can be mutated. To prevent this, you can deep freeze objects, as described in [this related article](/articles/s/javascript-deep-freeze-object).
diff --git a/articles/snippets/js-proxy-array-negative-index.md b/articles/snippets/js-proxy-array-negative-index.md
new file mode 100644
index 000000000..4d3a8c2f1
--- /dev/null
+++ b/articles/snippets/js-proxy-array-negative-index.md
@@ -0,0 +1,38 @@
+---
+title: Negative index in JavaScript array
+shortTitle: Negative index array proxy
+type: story
+tags: [javascript,array,proxy]
+author: chalarangelo
+cover: budapest-palace
+excerpt: Ever wanted to use negative indices in JavaScript arrays? Here's a simple way to do it using a Proxy.
+dateModified: 2022-10-02T05:00:00-04:00
+---
+
+`Array.prototype.slice()` provides an easy way to access elements from the end of an array, using a negative `start` value. While this sounds convenient, the resulting value is an array, so it's necessary to use an index to get an individual element.
+
+This is usually not too bad, but it's interesting to explore other options to understand the language better. In this case, we can use a `Proxy` object to allow accessing data in an array using negative indexes. To do so, an appropriate handler needs to be defined for the `get` trap.
+
+The trap's second argument corresponds to the passed index, however it's a string, so it must first be converted to a number using `Number()`. Then, `Array.prototype.length` can be used to calculate the position of the actual element. Finally, `Reflect.get()` can be used to get the value at the specific index, but expects its second argument to be a string.
+
+Putting everything together, this is what this looks like:
+
+```js
+const handler = {
+ get(target, key, receiver) {
+ const index = Number(key);
+ const prop = index < 0 ? `${target.length + index}` : key;
+ return Reflect.get(target, prop, receiver);
+ },
+};
+
+const createArray = (...elements) => {
+ const arr = [...elements];
+ return new Proxy(arr, handler);
+};
+
+let arr = createArray('a', 'b', 'c');
+
+arr[-1]; // 'c'
+arr[-1]; // 'b'
+```
diff --git a/articles/snippets/js-proxy-introduction.md b/articles/snippets/js-proxy-introduction.md
new file mode 100644
index 000000000..915617cb4
--- /dev/null
+++ b/articles/snippets/js-proxy-introduction.md
@@ -0,0 +1,54 @@
+---
+title: An Introduction to JavaScript Proxy
+shortTitle: JavaScript Proxy Introduction
+type: story
+tags: [javascript,object,proxy,pattern]
+author: chalarangelo
+cover: red-mountain-range
+excerpt: A quick introduction to the JavaScript Proxy object and where it can be used.
+dateModified: 2023-04-02T05:00:00-04:00
+---
+
+The JavaScript `Proxy` object is a relatively new addition to the language, having been introduced in ES6. It's based on the **software design pattern** of the same name, which creates a wrapper for another object, **intercepting** and **redefining** fundamental operations for that object.
+
+A `Proxy` object is defined as follows:
+
+```js
+const proxy = new Proxy(target, handler);
+```
+
+The `target` is the object that the proxy wraps around, while the `handler` is an object that contains one or more **"traps"** - functions that intercept operations performed on the target object.
+
+There are a variety of available traps that can be used to customize the behavior of the target object. Here's a brief overview of all available traps and what each one does:
+
+- `get(target, prop, receiver)` - Intercepts calls to `target[prop]`.
+- `set(target, prop, value, receiver)` - Intercepts calls to `target[prop] = value`.
+- `has(target, prop)` - Intercepts calls to `prop in target`.
+- `apply(target, thisArg, argumentsList)` - Intercepts calls to functions.
+- `construct(target, argumentsList, newTarget)` - Intercepts calls to the `new` operator.
+- `defineProperty(target, prop, descriptor)` - Intercepts calls to `Object.defineProperty()`.
+- `deleteProperty(target, prop)` - Intercepts calls to `delete target[prop]`.
+- `getOwnPropertyDescriptor(target, prop)` - Intercepts calls to `Object.getOwnPropertyDescriptor()`.
+- `ownKeys(target)` - Intercepts calls to `Object.getOwnPropertyNames()` and `Object.getOwnPropertySymbols()`.
+- `getPrototypeOf(target)` - Intercepts calls to `Object.getPrototypeOf()`.
+- `setPrototypeOf(target, prototype)` - Intercepts calls to `Object.setPrototypeOf()`.
+- `isExtensible(target)` - Intercepts calls to `Object.isExtensible()`.
+- `preventExtensions(target)` - Intercepts calls to `Object.preventExtensions()`.
+
+There are many common and novel use-cases for the `Proxy` object, utilizing one or more of these traps. Here's a simple example that intercepts a `get` call and returns `null` if the property doesn't exist in the target object:
+
+```js
+const targetObj = { name: 'John', age: 30 };
+
+const handler = {
+ get(target, property) {
+ return property in target ? target[property] : null;
+ }
+};
+
+const proxyObj = new Proxy(targetObj, handler);
+
+proxyObj.name; // 'John'
+proxyObj.age; // 30
+proxyObj.address; // null
+```
diff --git a/articles/snippets/js-remove-array-duplicates.md b/articles/snippets/js-remove-array-duplicates.md
new file mode 100644
index 000000000..6cc64036a
--- /dev/null
+++ b/articles/snippets/js-remove-array-duplicates.md
@@ -0,0 +1,20 @@
+---
+title: "Tip: Remove duplicates from a JavaScript array"
+shortTitle: Remove duplicates from an array
+type: tip
+tags: [javascript,array]
+author: chalarangelo
+cover: architectural
+excerpt: Easily remove duplicates from a JavaScript array using the built-in `Set` object.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Removing duplicates from an array in JavaScript can be done in a variety of ways, such as using `Array.prototype.reduce()`, `Array.prototype.filter()` or even a simple `for` loop. But there's an easier alternative. JavaScript's built-in [`Set`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) object is described as a collection of values, where each value may occur only once. A `Set` object is also iterable, making it easily convertible to an array using the spread (`...`) operator.
+
+```js
+const nums = [1, 2, 2, 3, 1, 2, 4, 5, 4, 2, 6];
+
+[...new Set(nums)] // [1, 2, 3, 4, 5, 6]
+```
+
+You can wrap this in a helper method, which is exactly what the [uniqueElements](/js/s/unique-elements) snippet does. For more complex cases, such as unique objects in an array based on a specific key, you might want to take a look at [uniqueElementsBy](/js/s/unique-elements-by).
diff --git a/articles/snippets/js-remove-element-from-array.md b/articles/snippets/js-remove-element-from-array.md
new file mode 100644
index 000000000..587f331f3
--- /dev/null
+++ b/articles/snippets/js-remove-element-from-array.md
@@ -0,0 +1,43 @@
+---
+title: Remove an element from a JavaScript array
+shortTitle: Remove element from array
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: maple-leaf-palette
+excerpt: Did you know there are multiple ways to remove an element from an array? Let's take a look.
+dateModified: 2022-06-26T05:00:00-04:00
+---
+
+Removing a specific value or values from an array in JavaScript is a pretty common task. While not hard to accomplish, there are a few approaches available, each with their own pros and cons. Choosing the correct one ultimately depends on the use case.
+
+### Array.prototype.splice()
+
+This is probably the most common approach for removing elements from an array. While `Array.prototype.splice()` is a very versatile tool in your kit, you need to remember that it **mutates the original array**. On top of that, it returns the deleted elements instead of a new array.
+
+```js
+const arr = ['a', 'b', 'c'];
+const deleted = arr.splice(1, 1); // ['b']
+
+console.log(arr); // ['a', 'c']
+```
+
+If you're cool with mutating the array, `Array.prototype.splice()` might just be the solution you need.
+
+### Array.prototype.filter()
+
+Another option for removing elements from an array is `Array.prototype.filter()`. More versatile than `Array.prototype.splice()`, it **doesn't mutate the original array**, but instead returns a new one. However, there's a performance consideration to be made for larger arrays when the elements to be removed are only encountered once. `Array.prototype.filter()` will always iterate over all elements in the array, which might be impractical in some cases.
+
+```js
+const arr = ['a', 'b', 'c'];
+const filtered = arr.filter(el => el !== 'b'); // ['a', 'c']
+
+console.log(arr); // ['a', 'b', 'c']
+```
+
+Most of the time, `Array.prototype.filter()` is the best option for removing elements from an array.
+
+### Alternative options
+
+The previous two options should cover the vast majority of use cases. Yet, there are some other options available for removing elements from an array, which might be preferable in certain cases. For example, if you like the interface of `Array.prototype.splice()` but need immutability, the [shank snippet](/js/s/shank) might be the solution for you. Similarly, when working with large unsorted arrays, there's a [fast removal trick](/articles/s/js-fast-remove-array-element) that might be of interest to you.
+
diff --git a/articles/snippets/js-remove-trailing-zeros.md b/articles/snippets/js-remove-trailing-zeros.md
new file mode 100644
index 000000000..b69f6f92d
--- /dev/null
+++ b/articles/snippets/js-remove-trailing-zeros.md
@@ -0,0 +1,50 @@
+---
+title: How can I remove trailing zeros from a number in JavaScript?
+shortTitle: Remove trailing zeros from number
+type: story
+tags: [javascript,math]
+author: chalarangelo
+cover: island-corridor
+excerpt: When formatting decimal values in JavaScript, trailing zeros can be undesired. Here's how to deal with them.
+dateModified: 2022-05-08T05:00:00-04:00
+---
+
+JavaScript provides a couple of ways to format numeric values to a given precision. Namely, you can use `Number.prototype.toFixed()` and `Number.prototype.toPrecision()` to similar effect. However, neither of them deals with trailing zeros in the decimal part. Here's a few ways you can remove them:
+
+### Regular expression
+
+Provided that the number is converted to a fixed-point string, you can use a regular expression to remove trailing zeros. All you have to do is match the decimal point (`\.`) and replace any zeros after it (`0+`) until the end of the string (`$`).
+
+```js
+const toFixedWithoutZeros = (num, precision) =>
+ num.toFixed(precision).replace(/\.0+$/, '');
+
+toFixedWithoutZeros(1.001, 2); // '1'
+toFixedWithoutZeros(1.500, 2); // '1.50'
+```
+
+The main issue with this approach is that the regular expression will only remove trailing zeros if the decimal part has no other digits before them. Writing a regular expression to remove trailing zeros from any number is a bit more involved and gets harder to read. Thus, this approach is discouraged.
+
+### Multiply by 1
+
+A better way to remove trailing zeros is to multiply by `1`. This method will remove trailing zeros from the decimal part of the number, accounting for non-zero digits after the decimal point. The only downside is that the result is a numeric value, so it has to be converted back to a string.
+
+```js
+const toFixedWithoutZeros = (num, precision) =>
+ `${1 * num.toFixed(precision)}`;
+
+toFixedWithoutZeros(1.001, 2); // '1'
+toFixedWithoutZeros(1.500, 2); // '1.5'
+```
+
+### Number.parseFloat
+
+Similar to the previous approach, you can use `Number.parseFloat()` to remove trailing zeros from a number. This method also accounts for non-zero digits after the decimal point. We recommend this approach as it's the most readable.
+
+```js
+const toFixedWithoutZeros = (num, precision) =>
+ `${Number.parseFloat(num.toFixed(precision))}`;
+
+toFixedWithoutZeros(1.001, 2); // '1'
+toFixedWithoutZeros(1.500, 2); // '1.5'
+```
diff --git a/articles/snippets/js-replace-all-occurences-of-string.md b/articles/snippets/js-replace-all-occurences-of-string.md
new file mode 100644
index 000000000..1db31f604
--- /dev/null
+++ b/articles/snippets/js-replace-all-occurences-of-string.md
@@ -0,0 +1,38 @@
+---
+title: Replace all occurrences of a string in JavaScript
+shortTitle: Replace all occurrences of a string
+type: story
+tags: [javascript,string,regexp]
+author: chalarangelo
+cover: blue-computer
+excerpt: If you need to replace all occurrences of a string in JavaScript, you have a couple of options.
+dateModified: 2022-07-03T05:00:00-04:00
+---
+
+### String.prototype.replaceAll()
+
+Modern JavaScript engines have a built-in method called `String.prototype.replaceAll()`. This method can be used to replace all occurrences of a string in another string with relative ease.
+
+```js
+const str = 'Hello World';
+
+str.replaceAll('o', 'x'); // 'Hellx Wxrld'
+```
+
+Using `String.prototype.replaceAll()` is the recommended approach, as it's straightforward. If, however, you need to support older browsers, consider the option below.
+
+### String.prototype.replace()
+
+Before the introduction of `String.prototype.replaceAll()`, `String.prototype.replace()` was the method of choice for this sort of task. It's supported by all JavaScript engines, old and new and is very similar to `String.prototype.replaceAll()`.
+
+While this method doesn't replace all occurrences of a string, it supports regular expressions. Knowing the string to be replaced, a regular expression can be created with the global (`'g'`) flag. Then, it can be passed to `String.prototype.replace()` to replace all occurrences of the string. The only issue here is that special characters need to be escaped, so that they are matched correctly. The [escapeRegExp snippet](/js/s/escape-reg-exp) comes in handy for this task.
+
+```js
+const escapeRegExp = str => str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
+const replaceAll = (str, subStr, newSubStr) =>
+ str.replace(new RegExp(escapeRegExp(subStr), 'g'), newSubStr);
+
+const str = 'Hello World';
+
+replaceAll(str, 'o', 'x'); // 'Hellx Wxrld'
+```
diff --git a/articles/snippets/js-spread-operator-tricks.md b/articles/snippets/js-spread-operator-tricks.md
new file mode 100644
index 000000000..b6ea1bf85
--- /dev/null
+++ b/articles/snippets/js-spread-operator-tricks.md
@@ -0,0 +1,41 @@
+---
+title: 3 ways to use the JavaScript spread operator with arrays
+shortTitle: Array tricks using the spread operator
+type: story
+tags: [javascript,array]
+author: chalarangelo
+cover: succulent-crowd
+excerpt: JavaScript’s spread operator is a very versatile tool. Here are some simple ways to use it.
+dateModified: 2022-04-17T05:00:00-04:00
+---
+
+### Clone an array
+
+The spread operator can be used to clone an array into a new array. This trick can come in handy when working with arrays of primitives. However, it only shallow clones the array, meaning nested non-primitive values will not be cloned.
+
+```js
+const arr = [1, 2, 3];
+const arr2 = [...arr];
+// [1, 2, 3]
+```
+
+### Merge multiple arrays
+
+Using the spread operator, it’s possible to combine two or more arrays into one. You should think of this trick as cloning two arrays into a new one. Due to that, the shallow cloning limitation mentioned previously applies here, too.
+
+```js
+const arr1 = [1, 2, 3];
+const arr2 = [4, 5, 6];
+const combined = [...arr1, ...arr2];
+// [1, 2, 3, 4, 5, 6]
+```
+
+### Add items to an array
+
+Similarly to previous tricks, it’s possible to spread an array into a new one and add individual elements, too. This can also be combined with merging multiple arrays, if desired.
+
+```js
+const arr = [1, 2, 3];
+const arr2 = [0, ...arr, 4];
+// [0, 1, 2, 3, 4]
+```
diff --git a/articles/snippets/js-static-instance-methods.md b/articles/snippets/js-static-instance-methods.md
new file mode 100644
index 000000000..f81071052
--- /dev/null
+++ b/articles/snippets/js-static-instance-methods.md
@@ -0,0 +1,23 @@
+---
+title: What is the difference between static and instance methods?
+shortTitle: Static Instance Methods
+type: question
+tags: [javascript,object,function,class]
+author: chalarangelo
+cover: lake-runner
+excerpt: Static and instance methods are pretty easy to distinguish and serve different purposes. Learn all about them in this article.
+dateModified: 2022-01-30T05:00:00-04:00
+---
+
+Static methods belong to a class and don’t act on its instances. This means that they can’t be called on instances of the class. Instead, they're called on the class itself. They are often utility functions, such as functions to create or clone objects.
+
+Instance methods belong to the class prototype, which is inherited by all instances of the class. As such, they act on class instances and can be called on them.
+
+```jsx
+const arr = [1, 2, 3]; // An Array instance
+
+Array.isArray(arr); // Static method of Array
+arr.push(4); // Instance method of Array
+```
+
+In the context of ES6 classes, the `static` keyword is used to define static methods for a class. Conversely, methods not defined as `static` are instance methods.
diff --git a/articles/snippets/js-textcontent-or-innertext.md b/articles/snippets/js-textcontent-or-innertext.md
new file mode 100644
index 000000000..0fe198657
--- /dev/null
+++ b/articles/snippets/js-textcontent-or-innertext.md
@@ -0,0 +1,97 @@
+---
+title: How are HTMLElement.innerText and Node.textContent different?
+shortTitle: Differences between innerText and textContent
+type: question
+tags: [javascript,browser]
+author: chalarangelo
+cover: dark-city
+excerpt: While these two properties are very similar, there are some key differences that you should be aware of.
+dateModified: 2023-03-19T05:00:00-04:00
+---
+
+JavaScript provides two properties you can use to **access the text content of an element**: `Node.textContent` and `HTMLElement.innerText`. For the most part, these two appear to be interchangeable. In fact, many developers use them interchangeably, not knowing that there are important differences between the two.
+
+### Similarities
+
+I think it's helpful to identify the similarities of these two properties before diving into the differences. This will also clarify how they're used in most cases.
+
+Suppose you have an HTML element, containing some text:
+
+```html
+Hi there! My name is Bubbles .
+```
+
+Both of these properties will return the text content of the element, including the text content of any **child elements**. They will also **ignore any HTML tags** that may be present in the element's content. And, they can be used to **set the text content** of the element, too.
+
+```js
+const greeting = document.getElementById('greeting');
+
+greeting.innerText; // "Hi there! My name is Bubbles."
+greeting.textContent; // "Hi there! My name is Bubbles."
+
+greeting.innerText = 'Hello!'; // Hello!
+greeting.textContent = 'Hi!'; // Hi!
+```
+
+### Differences
+
+So far, these two properties appear to do the exact same thing. In fact, they both offer some convenient features that make them very useful. However, they start to exhibit some differences when the element's content is a little more complex.
+
+Take the following HTML element, for example:
+
+```html
+
+
+
Hi there! My name is Bubbles .
+
And I'm a dog .
+
+```
+
+Let's take a look at the output of each of these two properties and see how they differ.
+
+```js
+const card = document.querySelector('.card');
+
+card.innerText;
+/*
+"Hi there!
+My name is BUBBLES."
+*/
+
+card.textContent;
+/*
+"
+
+ p { color: red; }
+ strong { text-transform: uppercase; }
+ small { display: none; }
+
+ Hi there!My name is Bubbles.
+ And I'm a dog.
+"
+*/
+```
+
+It's drastically different in this case, right? `HTMLElement.innerText` is supposed to roughly **match what the user sees** in the browser. Another way to think of this is that its output should closely resemble what the user would get if they were to select the element's content and copy it to their clipboard.
+
+The first thing to notice, based on this definition, is that **hidden elements are ignored**. This applies to elements that don't render, such as `
+
+
+
+
+
+
+```
+
+After creating the SVG asset, you need only include the custom SVG favicon in the page's `` element and you're ready to go. Be sure to include a PNG fallback, if possible, with a rendered version of the icon in either palette:
+
+```html
+
+
+
+
+
+
+```
diff --git a/articles/snippets/reversed-list.md b/articles/snippets/reversed-list.md
new file mode 100644
index 000000000..7fff2e137
--- /dev/null
+++ b/articles/snippets/reversed-list.md
@@ -0,0 +1,27 @@
+---
+title: "Tip: Create a descending list of numbered items"
+shortTitle: Descending list
+type: tip
+tags: [webdev,html]
+author: chalarangelo
+cover: ancient-greek-building
+excerpt: Did you know there's an easy way to create a descending list of numbered items with pure HTML? Learn how with this handy tip.
+dateModified: 2021-06-22T05:00:00-04:00
+---
+
+Did you know there's an easy way to create a descending list of numbered items with pure HTML? The only thing you'll need is the `reversed` attribute. This boolean attribute is specific to `ol` elements and specifies that the list's elements are in reverse order (i.e. numbered from high to low).
+
+```html
+
+ My third favorite
+ My second favorite
+ My absolute favorite
+
+
+```
+
+Additionally, you can combine `reversed` with the `start` attribute which is an integer specifying the initial value of the list counter. For example, if you wanted to display the numbers 6 through 4 in a reversed 3-item list, you would simply add `start="6"`.
diff --git a/articles/snippets/select-focused-dom-element.md b/articles/snippets/select-focused-dom-element.md
new file mode 100644
index 000000000..6d6e4d8db
--- /dev/null
+++ b/articles/snippets/select-focused-dom-element.md
@@ -0,0 +1,19 @@
+---
+title: "Tip: Select the focused DOM element"
+shortTitle: Focused DOM element
+type: tip
+tags: [javascript,browser]
+author: chalarangelo
+cover: horse-sunset
+excerpt: Here's a quick and easy way to select the currently focused DOM element in JavaScript.
+dateModified: 2022-10-23T05:00:00-04:00
+---
+
+Finding the currently focused DOM element is trivial in modern CSS, using the `:focus` selector. You can also use it in JavaScript, in combination with `Document.querySelector()` to find the focused element. Yet, there's an even easier way to get the currently focused element in JavaScript, using the `Document.activeElement` property.
+
+```js
+const focusedElement = document.activeElement;
+// `focusedElement` is the currently focused element
+```
+
+Note that focusable elements vary depending on browser and operating system. Additionally, you should remember that focus and selection (i.e. content highlighting) are not the same thing.
diff --git a/articles/snippets/setup-python3-pip3-as-default.md b/articles/snippets/setup-python3-pip3-as-default.md
new file mode 100644
index 000000000..4d3be44e9
--- /dev/null
+++ b/articles/snippets/setup-python3-pip3-as-default.md
@@ -0,0 +1,31 @@
+---
+title: "Tip: Set up Python 3 and pip 3 as default"
+shortTitle: Python 3 and pip 3 setup
+type: tip
+tags: [python,setup]
+author: chalarangelo
+cover: avocado-slices
+excerpt: A very common problem when working with Python is having to remember the correct version. Luckily, there's an easy fix for that.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+One of the most common headaches when working with Python is having to remember to use Python 3.x instead of Python 2.x. Luckily, it's really easy to setup Python 3 and pip 3 as the defaults. You first need to figure out where each one is installed using the `which` command:
+
+```shell
+which python3 # /usr/local/bin/python3
+which pip3 # /usr/local/bin/pip3
+```
+
+Make a note of each response, so that you can add the paths as aliases to your shell environment's configuration file. Then, you can use `echo` to add a line for each one to either `.zshrc` or `.bashrc` depending on your environment:
+
+```shell
+# Linux or other bash environment
+echo "alias python=/usr/local/bin/python3" >> ~/.bashrc
+echo "alias pip=/usr/local/bin/pip3" >> ~/.bashrc
+
+# Mac OS or other zsh environment
+echo "alias python=/usr/local/bin/python3" >> ~/.zshrc
+echo "alias pip=/usr/local/bin/pip3" >> ~/.zshrc
+```
+
+And you're all done! `python` and `pip` are both mapped to their 3.x versions,
diff --git a/articles/snippets/technical-debt.md b/articles/snippets/technical-debt.md
new file mode 100644
index 000000000..557e6b54f
--- /dev/null
+++ b/articles/snippets/technical-debt.md
@@ -0,0 +1,49 @@
+---
+title: Technical debt
+type: story
+tags: [career,webdev,programming,management]
+author: chalarangelo
+cover: new-york
+excerpt: Learn what technical debt is, its causes and symptoms, and how to deal with it.
+dateModified: 2022-10-09T05:00:00-04:00
+---
+
+Technical debt is a jargon term that gets thrown around a lot in the software development industry. It's worth understanding what it means, how to spot it and how to deal with it, once it inevitably rears its ugly head.
+
+### Definition
+
+The term itself comes from a metaphor, in which the team's lack of understanding about the codebase leads to continuous disagreement. Continuously stumbling upon this situation slows down progress, feeling like paying interest on a loan.
+
+**Technical debt is effectively the natural result of writing code about something we don't have a proper understanding of.**
+
+### Causes
+
+But what causes technical debt in the first place? As hinted at by the previous definition, it arises from a **disagreement between business needs and how the software was written**. The root cause for such disagreements can either appear early on or later down the line.
+
+In the former case, a lack of understanding might have lead to laying the foundations incorrectly, therefore carrying the debt from the start. Poor design choices, lack of foresight and a lack of communication between the team members can all lead to this.
+
+In the latter case, the debt might have been incurred due to a change in the business requirements, which the software was not designed to handle. This is often the case with projects that move rapidly, making it hard to adapt to the changing needs.
+
+Interestingly enough, poor code and not following best practices only account for a portion of technical debt. This means that, while following best practices and writing clean code can help reduce the debt, they are usually not the main cause.
+
+### Symptoms
+
+So, how do you know if you have accumulated technical debt? It's not that hard to spot most of the time. **Lowered productivity** is usually one of the first signs. This translates to increased development time or effort estimates that are not met. This makes sense intuitively, as maintenance costs mount up and the codebase is not as easy to work with as it should be.
+
+Following lowered productivity, teams with accumulated technical debt might start to notice **decreased code quality**. When estimates are not met, developers might be tempted to cut corners and write code that is not as clean as it should be. This is a natural reaction to the pressure of meeting deadlines, but it can have a negative impact on the codebase in the long run.
+
+Finally, this spirals into a vicious cycle, as the codebase becomes harder to work with, which leads to more pressure, **lowered morale** and even more technical debt. This is why it's important to spot the symptoms early on and take action to reduce it.
+
+### Solutions
+
+Dealing with technical debt is not always easy, but it's not impossible either. The most important step is realizing that it exists and that it affects the team's productivity. Once that is done, the team can start to take action. Solutions vary, depending on the team, industry and nature of the technical debt itself.
+
+Broadly speaking, it's acceptable to **take on debt early on** to get the project off the ground. Identifying and keeping track of it ensures that the team knows where to start when the time comes to start dealing with it. This also helps figure out how much of an impact it has and how to prioritize maintenance tasks.
+
+As soon as the project is out of the door, the team should **start to reduce debt** or at least not take on any more. Prioritization can be based either on the impact or the effort required for each refactor. A combination of two can also be beneficial, as it can allow small maintenance tasks to fill in the gaps, while more impactful refactors are planned and coordinated accordingly.
+
+After getting to a manageable level, it's important to **keep technical debt in check**. Here's where having a process in place can work wonders. By knowing how to keep debt in check, when to take action and continuously working towards that goal, the team can ensure that the codebase is always in a good state.
+
+### Conclusion
+
+Technical debt is a natural, unavoidable part of software development. Miscommunication and lack of understanding can lead to it, resulting in lowered velocity and morale. Luckily, a bit of awareness, good communication and an actionable process can help reduce it and keep it in check.
diff --git a/articles/snippets/terminal-shortcuts-cheatsheet.md b/articles/snippets/terminal-shortcuts-cheatsheet.md
new file mode 100644
index 000000000..5fd07cfac
--- /dev/null
+++ b/articles/snippets/terminal-shortcuts-cheatsheet.md
@@ -0,0 +1,24 @@
+---
+title: Bash Shortcuts Cheat Sheet
+type: cheatsheet
+tags: [webdev,bash,cheatsheet]
+author: chalarangelo
+cover: terminal
+excerpt: Maximize your productivity when working with a bash or other shell terminal by using these keyboard shortcuts.
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+- Ctrl + C Terminate the command
+- Ctrl + Z Suspend the command
+- Ctrl + A Move to the start of the line
+- Ctrl + E Move to the end of the line
+- Ctrl + F Move forward one character
+- Ctrl + B Move backward one character
+- Ctrl + U Delete from the cursor to the start of the line
+- Ctrl + K Delete from the cursor to the end of the line
+- Ctrl + W Delete from the cursor to the start of the word
+- Ctrl + D Delete the character under the cursor
+- Ctrl + H Delete the character before the cursor
+- Ctrl + T Swap the character under the cursor with the previous one
+- Ctrl + L Clear the screen
+
diff --git a/articles/snippets/testing-async-react-components.md b/articles/snippets/testing-async-react-components.md
new file mode 100644
index 000000000..d543f8a14
--- /dev/null
+++ b/articles/snippets/testing-async-react-components.md
@@ -0,0 +1,159 @@
+---
+title: Testing React components that update asynchronously with React Testing Library
+shortTitle: Asynchronous component update testing
+type: story
+tags: [react,testing,event]
+cover: colorful-lounge
+excerpt: Testing React components that update asynchronously is pretty common. Learn how to deal with common issues and speed up your testing.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+### Components that update asynchronously
+
+Recently, while working on a side-project, we started using the [React DnD library](https://react-dnd.github.io/react-dnd), as we wanted to implement a multi-container drag and drop system with cards.
+
+After spending the better part of a day implementing the functionality, we decided to add some tests to ensure everything will keep working as expected. In the aforementioned project, we use [React Testing Library](https://testing-library.com/docs/react-testing-library/intro) to write tests for our components.
+
+While testing the drag functionality, we came across a very stubborn test. Here's a simplified version of our `Card` component:
+
+```jsx
+import React from 'react';
+import { useDrag } from 'react-dnd';
+
+const Card = ({
+ card: {
+ id,
+ title
+ }
+}) => {
+ const [style, drag] = useDrag({
+ item: { id, type: 'card' },
+ collect: monitor => ({
+ opacity: monitor.isDragging() ? 0 : 1
+ })
+ });
+
+ return (
+
+ {title}
+
+ );
+};
+```
+
+And here's the test we were trying to write originally:
+
+```jsx
+import React from 'react';
+import { fireEvent } from '@testing-library/react';
+import Card from './components/Card';
+// This a little helper we have written to connect to redux and react-dnd
+import renderDndConnected from './test_utils/renderDndConnected';
+
+describe(' ', () => {
+ let card;
+
+ beforeEach(() => {
+ const utils = renderDndConnected(
+
+ );
+ card = utils.container.querySelector('.card');
+ });
+
+ it('initial opacity is 1', () => {
+ expect(card.style.opacity).toEqual('1');
+ });
+
+ describe('when drag starts', () => {
+ beforeEach(() => {
+ fireEvent.dragStart(card);
+ });
+
+ it('opacity is 0', () => {
+ expect(card.style.opacity).toEqual('0');
+ });
+ });
+});
+```
+
+### The dreaded `act(...)` warning
+
+While the test was obviously not working, the console was constantly nagging about wrapping the test in `act()`:
+
+```
+When testing, code that causes React state updates should be wrapped into act(...):
+
+act(() => {
+ /* fire events that update state */
+});
+/* assert on the output */
+
+This ensures that you're testing the behavior the user would see in the browser.
+```
+
+This message wasn't very helpful in identifying the underlying issue. The only thing it highlighted was that the test didn't update the component style immediately. There were pending updates after the test completed. To put it plainly, the test was failing because the `dragStart` event didn't immediately update the `Card` components' style (i.e. set the new `opacity`).
+
+As a side note, the `Card` component is connected to Redux, which might relate to the issue, but it would most likely happen even without Redux. That's probably due to the fact that `collect` takes some amount of time to run and send an update to the component.
+
+### Solving the issue
+
+Digging deeper, we found that apart from `act()`, there are also other options, such as `waitFor()` and `waitForDomChange()`. These seem more intuitive simply because of the name and way they're written (using either `async await` or promises). However, `waitForDomChange()` didn't work properly for our case and our version of `react-testing-library` (which shipped with `react-scripts`) was outdated and did not export `waitFor()`, which took us a good half an hour to figure out.
+
+After updating `react-testing-library`, we were still not ready to go, as the console started displaying the following error:
+
+```
+TypeError: MutationObserver is not a constructor
+```
+
+This required some searching, which eventually led us to [this issue](https://github.com/testing-library/react-testing-library/issues/662) which helped us figure out that a solution was to replace the `test` script in our `package.json` with this line:
+
+```json
+{
+ // ...
+ "scripts": {
+ "test": "react-scripts test --env=jsdom-fourteen"
+ // ...
+ }
+}
+```
+
+Now to finally write a test that works! As mentioned above, we opted to use `waitFor()` from `react-testing-library`, which was actually the only change to the original testing code, except for the dependency bump and the script change described above. Here's the test after making the necessary changes:
+
+```jsx
+import React from 'react';
+import { fireEvent, waitFor } from '@testing-library/react';
+// This a little helper we have written to connect to redux and react-dnd
+import renderDndConnected from './test_utils/renderDndConnected';
+import Card from './components/Card';
+
+describe(' ', () => {
+ let card;
+
+ beforeEach(() => {
+ const utils = renderDndConnected(
+
+ );
+ card = utils.container.querySelector('.card');
+ });
+
+ it('initial opacity is 1', () => {
+ expect(card.style.opacity).toEqual('1');
+ });
+
+ describe('when drag starts', () => {
+ beforeEach(() => {
+ fireEvent.dragStart(card);
+ });
+
+ it('opacity is 0', async() => {
+ await waitFor(() => expect(card.style.opacity).toEqual('0'));
+ });
+ });
+});
+```
+
+### Summary
+
+- A message about code that causes React state updates not being wrapped in `act(...)` might indicate that a component updated after the test ended.
+- Using `waitFor()` can solve the issue by making tests asynchronous, but you might need to bump your `react-testing-library` version if you are using older versions of `react-scripts`.
+- If you see errors related to `MutationObserver`, you might need to change your `test` script to include `--env=jsdom-fourteen` as a parameter.
diff --git a/articles/snippets/testing-react-portals.md b/articles/snippets/testing-react-portals.md
new file mode 100644
index 000000000..d270f84c8
--- /dev/null
+++ b/articles/snippets/testing-react-portals.md
@@ -0,0 +1,36 @@
+---
+title: Testing React portals
+shortTitle: Portal testing
+type: story
+tags: [react,testing]
+author: chalarangelo
+cover: portal-timelapse
+excerpt: Testing React components that use portals can be difficult until you understand what you really need to be testing.
+dateModified: 2022-03-13T05:00:00-04:00
+---
+
+Testing React components can get pretty complicated, especially when dealing with portals. While they seem intimidating, what they are in essence is a way to render a component in a different place in the DOM. Apart from that, when writing tests, one should avoid testing framework internals. This obviously applies to React internals as well.
+
+Putting these two points together, all we really care about when testing React portals is if the **portalized output** is correct. Based on that, mocking portals shouldn't be all that hard. We just need to mock `ReactDOM.createPortal()` to render the input element in place. Here's what that looks like in Jest:
+
+```jsx
+describe('MyComponent', () => {
+ beforeAll(() => {
+ ReactDOM.createPortal = jest.fn((element, node) => {
+ return element;
+ });
+ });
+
+ afterEach(() => {
+ ReactDOM.createPortal.mockClear();
+ });
+
+ it('should render correctly', () => {
+ const component = renderer.create(Hello World! );
+
+ expect(component.toJSON()).toMatchSnapshot();
+ });
+});
+```
+
+This kind of mock will work in most cases and it will help ensure that the portalized output is correct. It comes with some caveats, though. First and foremost, the tested DOM is different from the actual DOM of the application. This can make tests less robust, reducing confidence in their result. Secondly, issues that might arise from the use of portals, such as the portal node missing, must be tested separately.
diff --git a/articles/snippets/testing-redux-connected-components.md b/articles/snippets/testing-redux-connected-components.md
new file mode 100644
index 000000000..45e31ab81
--- /dev/null
+++ b/articles/snippets/testing-redux-connected-components.md
@@ -0,0 +1,69 @@
+---
+title: Testing Redux-connected components with React Testing Library
+shortTitle: Redux-connected components testing
+type: story
+tags: [react,testing]
+author: chalarangelo
+cover: sparkles
+excerpt: Testing Redux-connected components is pretty common. Learn how to use this simple utility function to speed up your testing.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+Testing Redux-connected components with React Testing Library is a very common scenario. However, it might be a little complicated without the proper tools and you could end up repeating yourself. This is especially true when writing the boilerplate to connect to your redux store.
+
+Here's a simple utility function adapted from [React Testing Library's docs on the subject](https://testing-library.com/docs/example-react-redux) to help you speed up your testing:
+
+```jsx
+// src/test/utils/renderConnected.js
+import React from 'react';
+import { render } from '@testing-library/react';
+import { createStore } from 'redux';
+import { Provider } from 'react-redux';
+// Replace this with the appropriate imports for your project
+import { reducer, reducerInitialState } from './myReduxStore';
+
+const renderConnected = (
+ ui, {
+ initialState = reducerInitialState,
+ store = createStore(reducer, initialState),
+ ...renderOptions
+ } = {}
+) => {
+ const Wrapper = ({ children }) => (
+ {children}
+ );
+ return render(ui, { wrapper: Wrapper, ...renderOptions});
+};
+
+export default renderConnected;
+```
+
+This utility uses the `createStore` function and the `` component to wrap a redux-connected component to the passed state. Then it uses React Testing Library's `render` to finally render the result.
+
+Remember to replace `import` statements with the appropriate files and exports to set up the utility as necessary. After creating the utility function and saving it in an appropriate file, you can use it like this:
+
+```jsx
+// src/test/SomeComponent.test.jsx
+import React from 'react';
+// Replace this with the appropriate location of your component
+import SomeComponent from 'src/components/SomeComponent';
+// Replace this with the appropriate location of your testing utility
+import renderConnected from 'src/test/utils/renderConnected';
+
+describe(' ', () => {
+ let wrapper, getByText;
+ const initialState = {
+ // ... Add your initial testing state here
+ };
+
+ beforeEach(() => {
+ const utils = renderConnected( , { initialState });
+ wrapper = utils.container;
+ getByText = utils.getByText;
+ });
+
+ it('renders the component', () => {
+ expect(wrapper.querySelector('.some-component')).toBeInTheDocument();
+ });
+});
+```
diff --git a/articles/snippets/testing-stateful-ui-components.md b/articles/snippets/testing-stateful-ui-components.md
new file mode 100644
index 000000000..aa5bf2047
--- /dev/null
+++ b/articles/snippets/testing-stateful-ui-components.md
@@ -0,0 +1,54 @@
+---
+title: An approach to testing stateful React components
+shortTitle: Stateful component testing
+type: story
+tags: [react,testing]
+author: chalarangelo
+cover: lake-trees
+excerpt: Testing stateful React components is not difficult, but did you know there's a solution that doesn't involve testing state directly?
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Some time ago, I was tasked with writing tests for a handful of React components, an otherwise mundane and uninspiring task, that somehow ended with a "Eureka!" moment for me. The specifics of the project and its components are of little importance, however the key detail is that I was working with stateful React components that are used daily by a large team and, as such, are refactored and updated quite often.
+
+My initial approach consisted of writing some simple tests, such as checking if the component is rendered properly and if certain events fire appropriately. In doing so, I was comparing state directly with the result I was expecting, having the component's code right next to my assertions. Of course, this isn't bad by anyone's standards, but for a codebase with many moving parts, it is not the greatest idea. Let me show you an example why:
+
+```js
+context('the component is initialized in a collapsed state', function() {
+ let wrapper;
+ beforeEach(function(){
+ wrapper = mount( );
+ });
+
+ it('component state.expanded is false', function() {
+ expect(wrapper.state('expanded')).to.be.false;
+ });
+});
+```
+
+In this test, we check if the component's state has `expanded` equal to `false`. Our test will pass, as long as this simple condition is true. It's a very simple test that should be easy to understand even for someone completely unfamiliar with the codebase.
+
+However, over time the component's implementation might change. What happens if `expanded` in our state ends up meaning something different? Or worse yet, if it isn't reflected the same way in the interface?
+
+Enter my "Eureka!" moment:
+
+> The application's UI should always be considered the result of combining the component's props and state.
+
+The above statement implies that a component's state can be considered a black box while testings, an abstraction layer that should not be accessed unless absolutely necessary. So, instead of the test presented above, we should be doing something more like this:
+
+```js
+context('the component is initialized in a collapsed state', function() {
+ let wrapper;
+ beforeEach(function(){
+ wrapper = mount( );
+ });
+
+ it('component does not have the expanded class', function() {
+ expect(wrapper.find('div').hasClass('expanded')).to.be.false;
+ });
+});
+```
+
+Our test is still easy to read and understand, but it's a better test in general.
+
+By directly checking the DOM instead of the component's state, we provide information about the component's output to future code authors, instead of asking them to keep the existing implementation intact. It seems like a better way to document the component and it's easier to track future changes should someone refactor the UI in such a way that the DOM representation of the component is altered.
diff --git a/articles/snippets/the-case-for-javascript-trailing-commas.md b/articles/snippets/the-case-for-javascript-trailing-commas.md
new file mode 100644
index 000000000..c95323244
--- /dev/null
+++ b/articles/snippets/the-case-for-javascript-trailing-commas.md
@@ -0,0 +1,48 @@
+---
+title: The case for trailing commas in JavaScript
+shortTitle: Trailing commas in JavaScript
+type: story
+tags: [javascript,webdev]
+author: chalarangelo
+cover: contemporary-desk
+excerpt: Trailing commas are not without controversy. Here's why I think you should use them.
+dateModified: 2023-03-12T05:00:00-04:00
+---
+
+JavaScript's syntactic features are notorious for sparking debates among developers, with semicolons and tabs vs. spaces being the most common examples. However, trailing commas are a feature that isn't discussed as much, even though I believe there's merit to using them.
+
+JavaScript has allowed trailing commas in array and object literals since the **ES5 specification**. Adding a trailing comma is completely valid and will not cause any errors or alter the code in any way. For example, the two statements below are exactly the same:
+
+```js
+[1, 2, 3]; // [1, 2, 3]
+[1, 2, 3,]; // [1, 2, 3]
+```
+
+This example might look strange, and indeed it's not necessarily the prettiest sight. Where trailing commas start to feel more useful is when working with multiline arrays or objects. For example, consider the following object:
+
+```js
+const obj = {
+ a: 1,
+ b: 2,
+ c: 3
+};
+```
+
+There's nothing wrong with this code snippet, except if we want to make a change to the object. In that case, we will have to add a comma to the last line, before adding a new property. A similar issue arises if we reorder the properties. In that case, a comma might end up missing from the line that was previously last. Finally, if we want consistency, removing the last property will also require the removal of the comma from the line before it.
+
+None of these scenarios are uncommon, as you are well aware. Even more so, these start becoming a little more annoying when you factor in **version control**. A single property addition will require two lines to be altered. This can make diffs harder to read and review, and can also cause merge conflicts more often than you think.
+
+I think it's clear by now that trailing commas can improve **code readability** and increase **diff clarity**. This is not a new idea and has been suggested by popular style guides for years, especially in multiline array and object literals.
+
+As with most things, ESLint has a rule for this. The `comma-dangle` rule can be used to enforce trailing commas in both single-line and multiline situations. You can even go further and customize it for different types of literals, such as arrays, objects, functions, and imports/exports. My personal recommendation is to **enforce trailing commas only for multiline literals**:
+
+```js
+{
+ "rules": {
+ // Other rules ...
+ "comma-dangle": ["error", "always-multiline"]
+ }
+}
+```
+
+This way you get all the benefits of trailing commas, without having to look at the potentially confusing trailing commas in single-line literals. As a final note, bear in mind that style decisions should always be discussed with your team and agreed upon.
diff --git a/articles/snippets/typographic-scale-basics.md b/articles/snippets/typographic-scale-basics.md
new file mode 100644
index 000000000..e3f076b3d
--- /dev/null
+++ b/articles/snippets/typographic-scale-basics.md
@@ -0,0 +1,61 @@
+---
+title: Typographic scale basics
+type: story
+tags: [css,webdev,typography]
+author: chalarangelo
+cover: typography
+excerpt: Typography might seem intimidating, but you can quickly and easily create a simple typographic scale with this basic technique.
+dateModified: 2021-11-07T16:34:37+03:00
+---
+
+Building a typographic scale might seem hard. Yet it's not all that difficult, as long as you learn some basic techniques and principles.
+
+The first steps are to pick a **font family**, a starting value for the **font size** and a ratio which will serve as the **scaling factor**. Common values for these variables are the Roboto font family, a great choice due to its many different font weights, a starting font size of `18px` and a ratio of `1.618`, which is the golden ratio.
+
+Based on these values, the basis of our typographic scale is an element with `font-size: 18px` and `line-height: 1.618`. Notice that the ratio is also applied to the line height. This allows the text to breathe a little more and makes it easier to read, while creating a consistent vertical rhythm.
+
+Next, we are going to apply our ratio to **scale the font up or down**, as necessary. For example, we can multiply once by `1.618` for a sub heading, twice for a normal heading and three times for a large heading (e.g. our website's name on the home page). Similarly, we can scale the font down by dividing by our ratio to make elements less visually important (e.g. footnotes).
+
+While this gives us a pretty solid setup, some elements might not look properly emphasized. To deal with this, we can use **font weight** to increase or decrease the visual importance of some elements. We could, for example, make headings bolder to make them more important. We could also make footnotes slightly bold to emphasize them as their font size is very small and they might get overlooked.
+
+Putting it all together, we should end up with a typographic scale that looks similar to this:
+
+
+
+```css
+:root {
+ --font-family: 'Roboto', sans-serif;
+ --font-size: 18px;
+ --font-weight: 300;
+ --line-height: 1.618;
+}
+
+* {
+ font-family: var(--font-family);
+ font-size: var(--font-size);
+ font-weight: var(--font-weight);
+ line-height: var(--line-height);
+}
+
+.sub-heading {
+ --font-size: 1.618rem;
+ --font-weight: 600;
+}
+
+.heading {
+ --font-size: 2.618rem;
+ --font-weight: 400;
+}
+
+.large-heading {
+ --font-size: 4.236rem;
+ --font-weight: 500;
+}
+
+.footnote {
+ --font-size: 0.618rem;
+ --font-weight: 500;
+}
+```
+
+The above example is a very simple starting point to build your own typographic scale, applying some simple principles to create a visual hierarchy that feels natural and works well. Feel free to tweak the starting values of the variables and experiment to get the best result for your designs.
diff --git a/articles/snippets/zooming-accessibility-tips.md b/articles/snippets/zooming-accessibility-tips.md
new file mode 100644
index 000000000..48061d358
--- /dev/null
+++ b/articles/snippets/zooming-accessibility-tips.md
@@ -0,0 +1,27 @@
+---
+title: Why using maximum-scale can harm your page's accessibility
+shortTitle: Accessibility and maximum-scale
+type: story
+tags: [webdev]
+author: chalarangelo
+cover: camera-zoom
+excerpt: Using the viewport meta tag incorrectly can harm your website's accessibility. Learn how to prevent problems with this handy guide.
+unlisted: true
+dateModified: 2021-06-12T19:30:41+03:00
+---
+
+Using the `"viewport"` meta tag incorrectly can cause some serious accessibility issues for people with low vision.
+
+The most common and, for the vast majority of cases, correct setup for said tag looks something like the first example below. However, there are websites that might do something like the second example, employing `maximum-scale=1.0` as part of their meta tag:
+
+```html
+
+
+
+
+
+```
+
+The reason this is a bad practice is that `maximum-scale=1.0` will disable the pinch zoom functionality on certain mobile devices, forcing people to view the website a certain way and taking away their ability to zoom in and out. This is the exact reason you should avoid it, allowing you to meet user's needs and provide a better user experience.
+
+On a side note, even if you have some extraordinary reason for applying this, you should know that some browser and device combos such as Chrome on Android might respect the meta tag's suggestion, while others such as iOS 10 ignore the suggestion entirely, so you should be aware that you might not be delivering a consistent user experience for all of your users.