Unsplash link optimization
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 336 KiB After Width: | Height: | Size: 902 KiB |
@ -14,7 +14,7 @@ Developers will most likely argue for the rest of eternity about the most produc
|
|||||||
|
|
||||||
2. GitLens
|
2. GitLens
|
||||||
[GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) is a very powerful collaboration tool for VS Code. It provides many useful tools for git such as blame, code authorship, activity heatmaps, recent changes, file history and even commit search.
|
[GitLens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) is a very powerful collaboration tool for VS Code. It provides many useful tools for git such as blame, code authorship, activity heatmaps, recent changes, file history and even commit search.
|
||||||
|
|
||||||
3. Debugger for Chrome
|
3. Debugger for Chrome
|
||||||
[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome) allows you to debug your JavaScript code in Chrome or Chromium. Breakpoints, call stack inspection and stepping inside a function are only some of its features.
|
[Debugger for Chrome](https://marketplace.visualstudio.com/items?itemName=msjsdiag.debugger-for-chrome) allows you to debug your JavaScript code in Chrome or Chromium. Breakpoints, call stack inspection and stepping inside a function are only some of its features.
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ Developers will most likely argue for the rest of eternity about the most produc
|
|||||||
[Bookmarks](https://marketplace.visualstudio.com/items?itemName=alefragnani.Bookmarks) is one of those extensions that will significantly reduce your time jumping between different files, as it allows you to save important positions and navigate back to them easily and quickly.
|
[Bookmarks](https://marketplace.visualstudio.com/items?itemName=alefragnani.Bookmarks) is one of those extensions that will significantly reduce your time jumping between different files, as it allows you to save important positions and navigate back to them easily and quickly.
|
||||||
|
|
||||||
6. TODO Highlight
|
6. TODO Highlight
|
||||||
[TODO Highlight](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight) simplifies tracking leftover tasks by allowing you to list all of your TODO annotations, as well as adding a handy background highlight to them to make them pop out immediately.
|
[TODO Highlight](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight) simplifies tracking leftover tasks by allowing you to list all of your TODO annotations, as well as adding a handy background highlight to them to make them pop out immediately.
|
||||||
|
|
||||||
7. Live Server
|
7. Live Server
|
||||||
[Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) gives you an easy way to serve web pages from VS Code, making previewing and debugging a lot easier. One of the core features is the live reload support that many developers are used to.
|
[Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) gives you an easy way to serve web pages from VS Code, making previewing and debugging a lot easier. One of the core features is the live reload support that many developers are used to.
|
||||||
@ -35,8 +35,8 @@ Developers will most likely argue for the rest of eternity about the most produc
|
|||||||
|
|
||||||
9. One Dark Pro
|
9. One Dark Pro
|
||||||
[One Dark Pro](https://marketplace.visualstudio.com/items?itemName=zhuangtongfa.Material-theme) is one of the most popular VS Code themes and with very good reason. It provides a clean theme with a nice palette that has great contrast and is very comfortable to use on a daily basis.
|
[One Dark Pro](https://marketplace.visualstudio.com/items?itemName=zhuangtongfa.Material-theme) is one of the most popular VS Code themes and with very good reason. It provides a clean theme with a nice palette that has great contrast and is very comfortable to use on a daily basis.
|
||||||
|
|
||||||
10. Fira Code
|
10. Fira Code
|
||||||
[Fira Code](https://github.com/tonsky/FiraCode) is not a traditional VS Code extension and might take a couple more steps to set up, but it's a superb programming font with ligatures that will help you scan code faster once you get used to it.
|
[Fira Code](https://github.com/tonsky/FiraCode) is not a traditional VS Code extension and might take a couple more steps to set up, but it's a superb programming font with ligatures that will help you scan code faster once you get used to it.
|
||||||
|
|
||||||
**Image credit:** [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -55,4 +55,4 @@ const isOdd = x => x % 2 === 1;
|
|||||||
arr.find(isOdd); // 1
|
arr.find(isOdd); // 1
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Edgar Chaparro](https://unsplash.com/@echaparro) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Edgar Chaparro](https://unsplash.com/@echaparro) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -21,4 +21,4 @@ This is hardly a new tip, but I think it deserves a spot on the list, as both of
|
|||||||
4. Keep an eye on your markup, performance and accessibility
|
4. Keep an eye on your markup, performance and accessibility
|
||||||
Last but not least, something that is probably already on your list, is optimizing your code. This includes everything from writing semantic markup and keeping requests to a minimum to optimizing for all device types, making your website accessible and ensuring fast load times. Keep in mind that websites have many moving parts that evolve and change over time, so it's a good idea to audit your website often with a tool like Lighthouse.
|
Last but not least, something that is probably already on your list, is optimizing your code. This includes everything from writing semantic markup and keeping requests to a minimum to optimizing for all device types, making your website accessible and ensuring fast load times. Keep in mind that websites have many moving parts that evolve and change over time, so it's a good idea to audit your website often with a tool like Lighthouse.
|
||||||
|
|
||||||
**Image credit:** [timJ](https://unsplash.com/@the_roaming_platypus?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [timJ](https://unsplash.com/@the_roaming_platypus?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -24,4 +24,4 @@ Before submitting your pull request for review, always take the time to review i
|
|||||||
5. Respond to reviews
|
5. Respond to reviews
|
||||||
Set some time aside to respond to reviews after submitting your pull request. Handle anything you can as soon as possible and start discussion whenever necessary to arrive to a solution. Use `--fixup` for changes suggested in review comments or add new commits to help reviewers parse new changes more easily. Finally, assume good intentions, be polite and thank your peers.
|
Set some time aside to respond to reviews after submitting your pull request. Handle anything you can as soon as possible and start discussion whenever necessary to arrive to a solution. Use `--fixup` for changes suggested in review comments or add new commits to help reviewers parse new changes more easily. Finally, assume good intentions, be polite and thank your peers.
|
||||||
|
|
||||||
**Image credit:** [Alexandru Acea](https://unsplash.com/@alexacea?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Alexandru Acea](https://unsplash.com/@alexacea?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -117,4 +117,4 @@ const str = 'Greek looks like this: γεια';
|
|||||||
*/
|
*/
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Kace Rodriguez](https://unsplash.com/@kace?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Kace Rodriguez](https://unsplash.com/@kace?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -23,4 +23,4 @@ Many developers find onboarding experience worrisome. Here are 6 helpful tips to
|
|||||||
|
|
||||||
- Socialize with other team members on Slack channels like _#random_ and _#watercooler_. Just because you're new to the team doesn't mean you shouldn't participate in casual conversations with other employees. They are social beings too and are probably looking forward to getting to know better new colleagues.
|
- Socialize with other team members on Slack channels like _#random_ and _#watercooler_. Just because you're new to the team doesn't mean you shouldn't participate in casual conversations with other employees. They are social beings too and are probably looking forward to getting to know better new colleagues.
|
||||||
|
|
||||||
**Image credit:** [Umer Sayyam](https://unsplash.com/@sayyam197?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Umer Sayyam](https://unsplash.com/@sayyam197?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -30,4 +30,4 @@ Google Chrome's developer tools are nothing short of amazing, but there are a fe
|
|||||||
7. EditThisCookie
|
7. EditThisCookie
|
||||||
[EditThisCookie](https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg?hl=en) is a powerful cookie manager extension, that allows you to add, delete, edit and even export and import cookies quickly and efficiently.
|
[EditThisCookie](https://chrome.google.com/webstore/detail/editthiscookie/fngmhnnpilhplaeedifhccceomclgfbg?hl=en) is a powerful cookie manager extension, that allows you to add, delete, edit and even export and import cookies quickly and efficiently.
|
||||||
|
|
||||||
**Image credit:** [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Fotis Fotopoulos](https://unsplash.com/@ffstop?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -31,4 +31,4 @@ Responsiveness is often thought in terms of screen size or mobile vs desktop, bu
|
|||||||
8. Organize your content
|
8. Organize your content
|
||||||
A website's layout should be easy to scan, understand and find the content that is relevant to the user. Good organization with clear sections and properly groupped content provides a better user experience for all users, regardless of device or accessibility needs.
|
A website's layout should be easy to scan, understand and find the content that is relevant to the user. Good organization with clear sections and properly groupped content provides a better user experience for all users, regardless of device or accessibility needs.
|
||||||
|
|
||||||
**Image credit:** [AbsolutVision](https://unsplash.com/@freegraphictoday?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [AbsolutVision](https://unsplash.com/@freegraphictoday?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -35,4 +35,4 @@ It's as easy to forget about breaks as it is to start working late. Try to set a
|
|||||||
|
|
||||||
**[Looking for a work from home role/job? Check out Jooble!](https://jooble.org/jobs-work-from-home)**
|
**[Looking for a work from home role/job? Check out Jooble!](https://jooble.org/jobs-work-from-home)**
|
||||||
|
|
||||||
**Image credit:** [Goran Ivos](https://unsplash.com/@goran_ivos?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Goran Ivos](https://unsplash.com/@goran_ivos?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -110,4 +110,4 @@ async () => {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Katie Burkhart](https://unsplash.com/@katieanalyzes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Katie Burkhart](https://unsplash.com/@katieanalyzes?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -7,17 +7,17 @@ cover: blog_images/breaking-react.jpg
|
|||||||
excerpt: As powerful as React is, it is also quite fragile at places. Did you know that just a few lines are more than enough to break your entire React application?
|
excerpt: As powerful as React is, it is also quite fragile at places. Did you know that just a few lines are more than enough to break your entire React application?
|
||||||
---
|
---
|
||||||
|
|
||||||
I am by no means an expert React engineer, but I have a couple years of experience under my belt. While React is an extremely powerful library for building user interfaces, it is also quite fragile at places. A very common bug I have encountered is caused by direct DOM manipulation in combination with React. This is not exactly an anti-pattern, but under the right circumstances it can break your entire React application and might be hard to debug.
|
I am by no means an expert React engineer, but I have a couple years of experience under my belt. While React is an extremely powerful library for building user interfaces, it is also quite fragile at places. A very common bug I have encountered is caused by direct DOM manipulation in combination with React. This is not exactly an anti-pattern, but under the right circumstances it can break your entire React application and might be hard to debug.
|
||||||
|
|
||||||
Here's [a minimal example](https://codepen.io/chalarangelo/pen/jOEojVJ?editors=0010) of how one can reproduce this bug, before we dive into explaining the problem and how to fix it:
|
Here's [a minimal example](https://codepen.io/chalarangelo/pen/jOEojVJ?editors=0010) of how one can reproduce this bug, before we dive into explaining the problem and how to fix it:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
const destroyElement = () =>
|
const destroyElement = () =>
|
||||||
document.getElementById('app').removeChild(document.getElementById('my-div'));
|
document.getElementById('app').removeChild(document.getElementById('my-div'));
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
const [elementShown, updateElement] = React.useState(true);
|
const [elementShown, updateElement] = React.useState(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div id='app'>
|
<div id='app'>
|
||||||
<button onClick={() => destroyElement()}>
|
<button onClick={() => destroyElement()}>
|
||||||
@ -40,10 +40,10 @@ This looks like a pretty simple React application, with a container, two buttons
|
|||||||
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
|
Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
|
||||||
```
|
```
|
||||||
|
|
||||||
This might still be cryptic, so let me explain what is going on. React uses its own representation of the DOM, called a virtual DOM, in order to figure out what to render. Usually, the virtual DOM will match the current DOM structure and React will process changes in props and state, updating the virtual DOM and then sending the necessary changes to the real DOM.
|
This might still be cryptic, so let me explain what is going on. React uses its own representation of the DOM, called a virtual DOM, in order to figure out what to render. Usually, the virtual DOM will match the current DOM structure and React will process changes in props and state, updating the virtual DOM and then sending the necessary changes to the real DOM.
|
||||||
|
|
||||||
However, in this case React's virtual DOM and the real DOM are different, because of `destroyElement()` removing the `#my-div` element. As a result, when React tries to update the real DOM with the changes from the virtual DOM, the `#my-div` element cannot be removed as it doesn't exist anymore. This results in the above exception being thrown and your application breaking.
|
However, in this case React's virtual DOM and the real DOM are different, because of `destroyElement()` removing the `#my-div` element. As a result, when React tries to update the real DOM with the changes from the virtual DOM, the `#my-div` element cannot be removed as it doesn't exist anymore. This results in the above exception being thrown and your application breaking.
|
||||||
|
|
||||||
This example is short and easy to resolve, by refactoring `destroyElement()` to be part of the `App` component and interact with its state, yet it showcases how fragile React can be under circumstances. Having a shared codebase, with many developers working on different things, can lead to issues like this being introduced and tracking them down can be rather tricky, which is why you might want to be very careful when directly manipulating the DOM when you use React.
|
This example is short and easy to resolve, by refactoring `destroyElement()` to be part of the `App` component and interact with its state, yet it showcases how fragile React can be under circumstances. Having a shared codebase, with many developers working on different things, can lead to issues like this being introduced and tracking them down can be rather tricky, which is why you might want to be very careful when directly manipulating the DOM when you use React.
|
||||||
|
|
||||||
**Image credit:** [Julia Joppien](https://unsplash.com/@vitreous_macula?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Julia Joppien](https://unsplash.com/@vitreous_macula?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -73,4 +73,4 @@ const filePaths = files
|
|||||||
- Does not use `Array.prototype.push()` or the spread (`...`) operator.
|
- Does not use `Array.prototype.push()` or the spread (`...`) operator.
|
||||||
- `O(cN)` complexity, `c` iterations per element, (`c`: length of the chain).
|
- `O(cN)` complexity, `c` iterations per element, (`c`: length of the chain).
|
||||||
|
|
||||||
**Image credit:** [Windows](https://unsplash.com/@windows?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Windows](https://unsplash.com/@windows?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -118,4 +118,4 @@ The iterative solution above makes the same calculations as the memoized one, ho
|
|||||||
|
|
||||||
However, you have to bear in mind what the actual use cases of your recursive code are and be very careful how you optimize them. Memoization can be a more powerful tool if a recursive function is called multiple times with different arguments, as its cache persists between calls, while iteration can be faster for recursive computations that are used less frequently. Always pay attention to your code and optimize for the cases you know or anticipate to be more common.
|
However, you have to bear in mind what the actual use cases of your recursive code are and be very careful how you optimize them. Memoization can be a more powerful tool if a recursive function is called multiple times with different arguments, as its cache persists between calls, while iteration can be faster for recursive computations that are used less frequently. Always pay attention to your code and optimize for the cases you know or anticipate to be more common.
|
||||||
|
|
||||||
**Image credit:** [Windows](https://unsplash.com/@windows?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Windows](https://unsplash.com/@windows?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -60,4 +60,4 @@ Using `timeit` to analyze the performance of the last two code examples, it's pr
|
|||||||
|
|
||||||
This pretty much applies to most mathematical list operation snippets, such as [difference](/python/s/difference), [symmetric_difference](/python/s/symmetric-difference) and [intersection](/python/s/intersection).
|
This pretty much applies to most mathematical list operation snippets, such as [difference](/python/s/difference), [symmetric_difference](/python/s/symmetric-difference) and [intersection](/python/s/intersection).
|
||||||
|
|
||||||
**Image credit:** [Kalen Emsley](https://unsplash.com/@kalenemsley?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Kalen Emsley](https://unsplash.com/@kalenemsley?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -53,4 +53,4 @@ Session storage stores a larger amount of data on the client's computer only for
|
|||||||
| Blockable by users | Yes | Yes | Yes |
|
| Blockable by users | Yes | Yes | Yes |
|
||||||
| Editable by users | Yes | Yes | Yes |
|
| Editable by users | Yes | Yes | Yes |
|
||||||
|
|
||||||
**Image credit:** [Jonathan Pielmayer](https://unsplash.com/@jonathanpielmayer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Jonathan Pielmayer](https://unsplash.com/@jonathanpielmayer?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -54,4 +54,4 @@ const copyToClipboard = str => {
|
|||||||
|
|
||||||
The final consideration before wrapping this up is respecting the user's previous interaction with the website, like having already selected some content. Luckily, we can now use some modern Javascript methods and properties like `DocumentOrShadowRoot.getSelection()`, `Selection.rangeCount`, `Selection.getRangeAt()`, `Selection.removeAllRanges()` and `Selection.addRange()` to save and restore the original document selection. You can find the final code with these improvements implemented in the [copyToClipboard snippet](/js/s/copy-to-clipboard/).
|
The final consideration before wrapping this up is respecting the user's previous interaction with the website, like having already selected some content. Luckily, we can now use some modern Javascript methods and properties like `DocumentOrShadowRoot.getSelection()`, `Selection.rangeCount`, `Selection.getRangeAt()`, `Selection.removeAllRanges()` and `Selection.addRange()` to save and restore the original document selection. You can find the final code with these improvements implemented in the [copyToClipboard snippet](/js/s/copy-to-clipboard/).
|
||||||
|
|
||||||
**Image credit:** [Kaitlyn Baker](https://unsplash.com/@kaitlynbaker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Kaitlyn Baker](https://unsplash.com/@kaitlynbaker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -21,4 +21,4 @@ Below is a list of the top 5 most commonly used pseudo-classes and their usage.
|
|||||||
- `:not()` is used to match everything except the given selector and can be useful in styling hard to select elements
|
- `:not()` is used to match everything except the given selector and can be useful in styling hard to select elements
|
||||||
- `:lang()` allows you to apply special styles based on the language of the document and is useful for multilingual websites
|
- `:lang()` allows you to apply special styles based on the language of the document and is useful for multilingual websites
|
||||||
|
|
||||||
**Image credit:** [Tj Holowaychuk](https://unsplash.com/@tjholowaychuk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Tj Holowaychuk](https://unsplash.com/@tjholowaychuk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -63,4 +63,4 @@ Finally, keep in mind the following useful tips for working with CSS variables:
|
|||||||
- CSS variables are case sensitive, so mind your capitalization. They can also be inlined in HTML like any other style (e.g. `<div style="--text-color: red">`).
|
- CSS variables are case sensitive, so mind your capitalization. They can also be inlined in HTML like any other style (e.g. `<div style="--text-color: red">`).
|
||||||
- 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);`).
|
- 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);`).
|
||||||
|
|
||||||
**Image credit:** [Pankaj Patel](https://unsplash.com/@pankajpatel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Pankaj Patel](https://unsplash.com/@pankajpatel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -46,4 +46,4 @@ Object.entries(data).forEach(e => console.log(e[0], e[1]));
|
|||||||
// [0, 3] [1, 4]
|
// [0, 3] [1, 4]
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Kaitlyn Baker](https://unsplash.com/@kaitlynbaker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Kaitlyn Baker](https://unsplash.com/@kaitlynbaker?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -77,4 +77,4 @@ excerpt: Flexbox allows you to create fluid layouts easily. If you find yourself
|
|||||||
- Items in a container are sorted by ascending `order` value and then by their source code order
|
- Items in a container are sorted by ascending `order` value and then by their source code order
|
||||||
- Might cause accessibility issues if used incorrectly
|
- Might cause accessibility issues if used incorrectly
|
||||||
|
|
||||||
**Image credit:** [Markus Spiske](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Markus Spiske](https://unsplash.com/@markusspiske?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -23,4 +23,4 @@ Co-authored-by: another-name <another-name@example.com>"
|
|||||||
- If a person's email is private, you can use their GitHub-provided `no-reply` email.
|
- If a person's email is private, you can use their GitHub-provided `no-reply` email.
|
||||||
- Leave one or preferrably two empty lines before any `Co-authored-by` trailers.
|
- Leave one or preferrably two empty lines before any `Co-authored-by` trailers.
|
||||||
|
|
||||||
**Image credit:** [Taylor Simpson](https://unsplash.com/@taylorgsimpson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Taylor Simpson](https://unsplash.com/@taylorgsimpson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -85,4 +85,4 @@ const equalsIgnoreOrder = (a, b) => {
|
|||||||
|
|
||||||
For a more detailed explanation, you should check out the [haveSameContents snippet](/js/s/have-same-contents).
|
For a more detailed explanation, you should check out the [haveSameContents snippet](/js/s/have-same-contents).
|
||||||
|
|
||||||
**Image credit:** [Irene Kredenets](https://unsplash.com/@ikredenets?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Irene Kredenets](https://unsplash.com/@ikredenets?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -55,4 +55,4 @@ toggleElements.forEach(el => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Matthew Smith](https://unsplash.com/@whale?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Matthew Smith](https://unsplash.com/@whale?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -51,4 +51,4 @@ if (x) {
|
|||||||
|
|
||||||
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 `new 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.
|
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 `new 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.
|
||||||
|
|
||||||
**Image credit:** [Louis Droege](https://unsplash.com/@lois184?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Louis Droege](https://unsplash.com/@lois184?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -51,4 +51,4 @@ In this example, we define a function, `initCounter`, that returns an object, wh
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Mark Tegethoff](https://unsplash.com/@tegethoff?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mark Tegethoff](https://unsplash.com/@tegethoff?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -77,4 +77,4 @@ myObj = {
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Aaron Burden](https://unsplash.com/@aaronburden?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Aaron Burden](https://unsplash.com/@aaronburden?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -51,4 +51,4 @@ console.dir([
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Evi Radauscher](https://unsplash.com/@eviradauscher?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Evi Radauscher](https://unsplash.com/@eviradauscher?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -85,4 +85,4 @@ 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, 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.
|
- 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.
|
||||||
|
|
||||||
**Image credit:** [Mega Caesaria](https://unsplash.com/@megacaesaria?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mega Caesaria](https://unsplash.com/@megacaesaria?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -7,20 +7,20 @@ cover: blog_images/javascript-for-in-for-of-foreach.jpg
|
|||||||
excerpt: Learn the differences between the three most commonly used iteration methods offered by JavaScript, which often confuse beginners and veterans alike.
|
excerpt: Learn the differences between the three most commonly used iteration methods offered by JavaScript, which often confuse beginners and veterans alike.
|
||||||
---
|
---
|
||||||
|
|
||||||
`for...in` is used to iterate over all enumerable properties of an object, including inherited enumerable properties.
|
`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.
|
This iteration statement can be used with arrays strings or plain objects, but not with `Map` or `Set` objects.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
for (let prop in ['a', 'b', 'c'])
|
for (let prop in ['a', 'b', 'c'])
|
||||||
console.log(prop); // 0, 1, 2 (array indexes)
|
console.log(prop); // 0, 1, 2 (array indexes)
|
||||||
|
|
||||||
for (let prop in 'str')
|
for (let prop in 'str')
|
||||||
console.log(prop); // 0, 1, 2 (string indexes)
|
console.log(prop); // 0, 1, 2 (string indexes)
|
||||||
|
|
||||||
for (let prop in {a: 1, b: 2, c: 3})
|
for (let prop in {a: 1, b: 2, c: 3})
|
||||||
console.log(prop); // a, b, c (object property names)
|
console.log(prop); // a, b, c (object property names)
|
||||||
|
|
||||||
for (let prop in new Set(['a', 'b', 'a', 'd']))
|
for (let prop in new Set(['a', 'b', 'a', 'd']))
|
||||||
console.log(prop); // undefined (no enumerable properties)
|
console.log(prop); // undefined (no enumerable properties)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -28,16 +28,16 @@ for (let prop in new Set(['a', 'b', 'a', 'd']))
|
|||||||
This iteration statement can be used with arrays, strings, `Map` or `Set` objects, but not with plain objects.
|
This iteration statement can be used with arrays, strings, `Map` or `Set` objects, but not with plain objects.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
for (let val of ['a', 'b', 'c'])
|
for (let val of ['a', 'b', 'c'])
|
||||||
console.log(val); // a, b, c (array values)
|
console.log(val); // a, b, c (array values)
|
||||||
|
|
||||||
for (let val of 'str')
|
for (let val of 'str')
|
||||||
console.log(val); // s, t, r (string characters)
|
console.log(val); // s, t, r (string characters)
|
||||||
|
|
||||||
for (let val of {a: 1, b: 2, c: 3})
|
for (let val of {a: 1, b: 2, c: 3})
|
||||||
console.log(prop); // TypeError (not iterable)
|
console.log(prop); // TypeError (not iterable)
|
||||||
|
|
||||||
for (let val of new Set(['a', 'b', 'a', 'd']))
|
for (let val of new Set(['a', 'b', 'a', 'd']))
|
||||||
console.log(val); // a, b, d (Set values)
|
console.log(val); // a, b, d (Set values)
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -54,4 +54,4 @@ While `forEach()` only iterates over arrays, it can access both the value and th
|
|||||||
);
|
);
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Tim Stief](https://unsplash.com/@timstief?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Tim Stief](https://unsplash.com/@timstief?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -27,4 +27,4 @@ const evenSum = data.filter(isEven).reduce(add); // 12
|
|||||||
|
|
||||||
In the above 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, allowing 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.
|
In the above 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, allowing 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.
|
||||||
|
|
||||||
**Image credit:** [Brent Payton](https://unsplash.com/@brentpayton?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Brent Payton](https://unsplash.com/@brentpayton?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -43,4 +43,4 @@ const nodeArray = [...nodes]; // [ <!DOCTYPE html>, html ]
|
|||||||
|
|
||||||
Note that the above example is the basis for the [nodeListToArray snippet](js/s/node-list-to-array).
|
Note that the above example is the basis for the [nodeListToArray snippet](js/s/node-list-to-array).
|
||||||
|
|
||||||
**Image credit:** [Holger Link](https://unsplash.com/@photoholgic?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Holger Link](https://unsplash.com/@photoholgic?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -51,7 +51,7 @@ for(let item of myList) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
In the above example, we implement a `LinkedList` data structure, that internally uses a `data` array where each item has a `value`, alongside some implementation-specific properties used to determine its position in the sequence. Objects constructed from this class are not iterable by default, so we define an iterator via the use of `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`.
|
In the above example, we implement a `LinkedList` data structure, that internally uses a `data` array where each item has a `value`, alongside some implementation-specific properties used to determine its position in the sequence. Objects constructed from this class are not iterable by default, so we define an iterator via the use of `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, allowing us to define multiple iterators for the same object. Here's an example of these concepts at play:
|
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, allowing us to define multiple iterators for the same object. Here's an example of these concepts at play:
|
||||||
|
|
||||||
@ -92,4 +92,4 @@ for(let item of myList.values()) {
|
|||||||
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, then finally returning the `Symbol.iterator` of the result, allowing iteration only over non-empty objects in the sequence and returning just the `value` for each one.
|
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, then finally returning the `Symbol.iterator` of the result, allowing iteration only over non-empty objects in the sequence and returning just the `value` for each one.
|
||||||
|
|
||||||
|
|
||||||
**Image credit:** [Daniele Levis Pelusi](https://unsplash.com/@yogidan2012?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [ian dooley](https://unsplash.com/@sadswim?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -59,4 +59,4 @@ listenOnce(
|
|||||||
); // 'Hello!' will only be logged on the first click
|
); // 'Hello!' will only be logged on the first click
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Josh Frenette](https://unsplash.com/@joshfrenette?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Josh Frenette](https://unsplash.com/@joshfrenette?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -65,4 +65,4 @@ for (let i = 0; i < 100; i ++)
|
|||||||
memoizedFibonacci(30); // ~50ms
|
memoizedFibonacci(30); // ~50ms
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Mark Tegethoff](https://unsplash.com/@tegethoff?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mark Tegethoff](https://unsplash.com/@tegethoff?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -54,4 +54,4 @@ As you can see in the above example, the spread operator either throws an error
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Edgar Chaparro](https://unsplash.com/@echaparro) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Edgar Chaparro](https://unsplash.com/@echaparro) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -46,4 +46,4 @@ window.location.replace(nextURL);
|
|||||||
|
|
||||||
As you can see, all three options will cause a page reload, which can be undesirable. Additionally, you can only set the URL, without any additional arguments, unlike using the History API. Finally, the Location API doesn't restrict you to same-origin URLs, which can be the cause of security issues if you are not careful.
|
As you can see, all three options will cause a page reload, which can be undesirable. Additionally, you can only set the URL, without any additional arguments, unlike using the History API. Finally, the Location API doesn't restrict you to same-origin URLs, which can be the cause of security issues if you are not careful.
|
||||||
|
|
||||||
**Image credit:** [Alexander Andrews](https://unsplash.com/@alex_andrews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Alexander Andrews](https://unsplash.com/@alex_andrews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -137,4 +137,4 @@ const { default: { key, port}, envType } = environment;
|
|||||||
- Named exports will be available by their names on the imported object.
|
- 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.
|
- Default export will be available as the `default` key on the imported object.
|
||||||
|
|
||||||
**Image credit:** [roman manukyan](https://unsplash.com/@romanukyan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [roman manukyan](https://unsplash.com/@romanukyan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -40,4 +40,4 @@ excerpt: Naming conventions, while not easy to enforce, make code easier to read
|
|||||||
- Prefix any variable or function with `_` to show intention for it to be 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.
|
- As a convention, this will not prevent other parts of the code from accessing it.
|
||||||
|
|
||||||
**Image credit:** [Paul Hanaoka](https://unsplash.com/@plhnk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Paul Hanaoka](https://unsplash.com/@plhnk?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -55,4 +55,4 @@ 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)).
|
**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)).
|
||||||
|
|
||||||
**Image credit:** [Hybrid](https://unsplash.com/@artbyhybrid?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Hybrid](https://unsplash.com/@artbyhybrid?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -64,4 +64,4 @@ 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
|
for (let i of range(8, 2, 2)) console.log(i); // Logs: 2, 4, 6
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Jayphen Simpson](https://unsplash.com/@jayphen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Jayphen Simpson](https://unsplash.com/@jayphen?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -48,4 +48,4 @@ While the above example works, it has to serialize and deserialize the whole obj
|
|||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
**Image credit:** [Joshua Ang](https://unsplash.com/@jangus231?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Joshua Ang](https://unsplash.com/@jangus231?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -7,11 +7,11 @@ cover: blog_images/javascript-singleton-proxy.jpg
|
|||||||
excerpt: Learn how to implement a singleton, a commonly used software design pattern, in JavaScript using the Proxy object.
|
excerpt: Learn how to implement a singleton, a commonly used software design pattern, in JavaScript using the Proxy object.
|
||||||
---
|
---
|
||||||
|
|
||||||
A singleton is an object-oriented software design pattern which ensures a given class is only ever instantiated once and can be quite useful in many different situations, such as creating global objects and components shared across an application. While JavaScript supports object-oriented programming, it doesn't seem to provide many simple options to implement this pattern.
|
A singleton is an object-oriented software design pattern which ensures a given class is only ever instantiated once and can be quite useful in many different situations, such as creating global objects and components shared across an application. While JavaScript supports object-oriented programming, it doesn't seem to 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, 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, which means that the most useful trap is `handler.construct()`, the trap for the `new` operator.
|
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, 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, which means that the most useful trap is `handler.construct()`, the trap for the `new` operator.
|
||||||
|
|
||||||
As the `handler` is itself an object, we can use it to store the unique instance of the class we want, if it has been instantiated, while also providing a trap for the `new` operator via `handler.construct()`. In doing so, we can create an object that can be easily 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.
|
As the `handler` is itself an object, we can use it to store the unique instance of the class we want, if it has been instantiated, while also providing a trap for the `new` operator via `handler.construct()`. In doing so, we can create an object that can be easily 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:
|
Here's the most basic version of a function that takes a `class` and converts it into a singleton, based on the above explanation:
|
||||||
|
|
||||||
@ -52,4 +52,4 @@ myObj2.printMsg(); // 'first'
|
|||||||
In the above example, you can see that the second time `MySingletonClass` is instantiated, nothing happens, due to the fact that an instance already exists, so it is returned instead of a new object being created. While this is the minimum implementation of a `singletonify` function, it can easily be extended to modify the behavior even further or even use some of the data passed to the constructor in subsequent calls to update the `instance` it holds.
|
In the above example, you can see that the second time `MySingletonClass` is instantiated, nothing happens, due to the fact that an instance already exists, so it is returned instead of a new object being created. While this is the minimum implementation of a `singletonify` function, it can easily be extended to modify the behavior even further or even use some of the data passed to the constructor in subsequent calls to update the `instance` it holds.
|
||||||
|
|
||||||
|
|
||||||
**Image credit:** [David Watkis](https://unsplash.com/@david_watkis?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [David Watkis](https://unsplash.com/@david_watkis?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -61,4 +61,4 @@ const printNums = async() => {
|
|||||||
printNums(); // Logs: 1, 2, 3 (2 and 3 log after 500ms)
|
printNums(); // Logs: 1, 2, 3 (2 and 3 log after 500ms)
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Kate Stone Matheson](https://unsplash.com/@kstonematheson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Kate Stone Matheson](https://unsplash.com/@kstonematheson?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -34,4 +34,4 @@ let b = 20;
|
|||||||
[a , b] = [b, a];
|
[a , b] = [b, a];
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [roman manukyan](https://unsplash.com/@romanukyan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [roman manukyan](https://unsplash.com/@romanukyan?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -45,4 +45,4 @@ const ItemListTitle = (count) => (
|
|||||||
|
|
||||||
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).
|
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).
|
||||||
|
|
||||||
**Image credit:** [Scott Webb](https://unsplash.com/@scottwebb?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Scott Webb](https://unsplash.com/@scottwebb?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -139,4 +139,4 @@ function f() {
|
|||||||
console.log(f.call({foo: 'hi'})); // 'hi'
|
console.log(f.call({foo: 'hi'})); // 'hi'
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [Prateek Katyal](https://unsplash.com/@prateekkatyal?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Prateek Katyal](https://unsplash.com/@prateekkatyal?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -67,4 +67,4 @@ Generally, `const` and `let` provide more of a headache-free experience for a va
|
|||||||
- If your environment/team allows it, prefer `const` and `let`over `var` to minimize headaches.
|
- 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.
|
- If possible, use only arrow functions or `function` declarations. Consistency can help reduce confusion.
|
||||||
|
|
||||||
**Image credit:** [Drew Dau](https://unsplash.com/@daunation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Drew Dau](https://unsplash.com/@daunation?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -27,4 +27,4 @@ When we talk about scope, we mean the visibility of one or more entities (e.g va
|
|||||||
|
|
||||||
**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.
|
**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.
|
||||||
|
|
||||||
**Image credit:** [Jp Valery](https://unsplash.com/@jpvalery?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Jp Valery](https://unsplash.com/@jpvalery?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -17,4 +17,4 @@ Node.js can be debugged using Chrome Developer Tools since `v6.3.0`. Here's a qu
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
**Image credit:** [David Clode](https://unsplash.com/@davidclode?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [David Clode](https://unsplash.com/@davidclode?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -27,4 +27,4 @@ Similarly, you can preload assets using the `rel="preload"` attribute, which are
|
|||||||
|
|
||||||
The only downside to preloading resources compared to prefetching is that [browser support](https://caniuse.com/#search=preload) might be low depending on when you are reading this.
|
The only downside to preloading resources compared to prefetching is that [browser support](https://caniuse.com/#search=preload) might be low depending on when you are reading this.
|
||||||
|
|
||||||
**Image credit:** [Dominik Kempf](https://unsplash.com/@dominik_kempf?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Dominik Kempf](https://unsplash.com/@dominik_kempf?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -25,4 +25,4 @@ excerpt: Learn how Python's lists and tuples are different and level up your cod
|
|||||||
|
|
||||||
Lists provide a more accessible API and should be used whenever similar types of objects need to be stored and are expected to change over the course of the application's execution. On the other hand, tuples should be used for immutable data, behaving more like constants than variables.
|
Lists provide a more accessible API and should be used whenever similar types of objects need to be stored and are expected to change over the course of the application's execution. On the other hand, tuples should be used for immutable data, behaving more like constants than variables.
|
||||||
|
|
||||||
**Image credit:** [Hasan Almasi](https://unsplash.com/@hasanalmasi?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Hasan Almasi](https://unsplash.com/@hasanalmasi?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -52,4 +52,4 @@ To put this another way, calling `setState()` in the root component without any
|
|||||||
|
|
||||||
[Continue on React rendering optimization](/blog/s/react-rendering-optimization)
|
[Continue on React rendering optimization](/blog/s/react-rendering-optimization)
|
||||||
|
|
||||||
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -45,4 +45,4 @@ Finally, remember that React's development builds are significantly slower than
|
|||||||
|
|
||||||
[Continue on React rendering state](/blog/s/react-rendering-state)
|
[Continue on React rendering state](/blog/s/react-rendering-state)
|
||||||
|
|
||||||
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -44,4 +44,4 @@ React-Redux provides two ways of connecting to its store, performing the necessa
|
|||||||
|
|
||||||
On the other hand, `useSelector` has no way of stopping a component from rendering when its parent component renders. When exclusively using `useSelector`, larger parts of the component tree will re-render due to Redux store updates than they would with `connect`, since there aren't other components using `connect` to prevent them from doing so. You can use `React.memo()` as necessary, to optimize this behavior by preventing unnecessary re-rendering.
|
On the other hand, `useSelector` has no way of stopping a component from rendering when its parent component renders. When exclusively using `useSelector`, larger parts of the component tree will re-render due to Redux store updates than they would with `connect`, since there aren't other components using `connect` to prevent them from doing so. You can use `React.memo()` as necessary, to optimize this behavior by preventing unnecessary re-rendering.
|
||||||
|
|
||||||
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Mahdiar Mahmoodi](https://unsplash.com/@mhdr_m?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -58,4 +58,4 @@ Note that the above implementation uses `defaultValue`, therefore it implies tha
|
|||||||
|
|
||||||
For a more detailed explanation of the component, as well as usage examples, you can check out the [Select component](/react/s/select).
|
For a more detailed explanation of the component, as well as usage examples, you can check out the [Select component](/react/s/select).
|
||||||
|
|
||||||
**Image credit:** [Robert Anasch](https://unsplash.com/@diesektion?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Robert Anasch](https://unsplash.com/@diesektion?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -59,4 +59,4 @@ Note: `a` is any valid quantifiable expression.
|
|||||||
|
|
||||||
Note that this cheatsheet is meant only as a starting point and is by no means a complete guide to all the features and nuances of regular expressions. You can also read [6 JavaScript Regular Expression features you can use today](/blog/s/6-javascript-regexp-tricks) for a deeper dive into some more advanced features.
|
Note that this cheatsheet is meant only as a starting point and is by no means a complete guide to all the features and nuances of regular expressions. You can also read [6 JavaScript Regular Expression features you can use today](/blog/s/6-javascript-regexp-tricks) for a deeper dive into some more advanced features.
|
||||||
|
|
||||||
**Image credit:** [Todd Quackenbush](https://unsplash.com/@toddquackenbush?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Todd Quackenbush](https://unsplash.com/@toddquackenbush?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -157,4 +157,4 @@ describe('<Card/>', () => {
|
|||||||
- 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`.
|
- 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.
|
- If you see errors related to `MutationObserver`, you might need to change your `test` script to include `--env=jsdom-fourteen` as a parameter.
|
||||||
|
|
||||||
**Image credit:** [Louis Hansel @shotsoflouis](https://unsplash.com/@louishansel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Louis Hansel @shotsoflouis](https://unsplash.com/@louishansel?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -66,4 +66,4 @@ describe('<SomeComponent/>', () => {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
**Image credit:** [israel palacio](https://unsplash.com/@othentikisra?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [israel palacio](https://unsplash.com/@othentikisra?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -47,8 +47,8 @@ context('the component is initialized in a collapsed state', function() {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Our test is still easy to read and understand, but it's a better test in general.
|
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Evan Clark](https://unsplash.com/@evanrclark?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Evan Clark](https://unsplash.com/@evanrclark?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -59,4 +59,4 @@ Putting it all together, we should end up with a typographic scale that looks si
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [chuttersnap](https://unsplash.com/@chuttersnap?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [chuttersnap](https://unsplash.com/@chuttersnap?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -23,4 +23,4 @@ The reason this is a bad practice is that `maximum-scale=1.0` will disable the p
|
|||||||
|
|
||||||
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.
|
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.
|
||||||
|
|
||||||
**Image credit:** [Ross Sneddon](https://unsplash.com/@rosssneddon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Ross Sneddon](https://unsplash.com/@rosssneddon?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
@ -9,4 +9,4 @@ excerpt: A short summary of your story up to 180 characters long.
|
|||||||
|
|
||||||
Write your blog post here.
|
Write your blog post here.
|
||||||
|
|
||||||
**Image credit:** [Someone](https://unsplash.com/...?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/code?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
**Image credit:** [Someone](https://unsplash.com/...?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)
|
||||||
|
|||||||
Reference in New Issue
Block a user