Rename articles prefixed with javascript-

This commit is contained in:
Angelos Chalaris
2023-05-18 23:24:53 +03:00
parent db4fc1d50b
commit f1931acb2c
106 changed files with 78 additions and 78 deletions

View File

@ -0,0 +1,78 @@
---
title: How can I add a key-value pair to a JavaScript object?
shortTitle: Add key-value pair to object
type: question
language: javascript
tags: [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 }
```

View File

@ -0,0 +1,89 @@
---
title: How do I compare two arrays in JavaScript?
shortTitle: JavaScript array comparison
type: question
language: javascript
tags: [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).

View File

@ -0,0 +1,38 @@
---
title: How can I check if a JavaScript array includes a specific value?
shortTitle: JavaScript array includes value
type: question
language: javascript
tags: [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](/js/s/pass-by-reference-or-pass-by-value). I highly recommend reading the previous article about [object comparison](/js/s/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
```

View File

@ -0,0 +1,59 @@
---
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
language: javascript
tags: [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
});
});
```

View File

@ -0,0 +1,109 @@
---
title: Introduction to arrow functions in JavaScript
shortTitle: Arrow functions introduction
type: story
language: javascript
tags: [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).

View File

@ -0,0 +1,125 @@
---
title: What are the differences between arrow functions and regular functions in JavaScript?
shortTitle: Arrow functions vs regular functions
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,94 @@
---
title: Asynchronous array loops in JavaScript
shortTitle: Asynchronous array loops
type: story
language: javascript
tags: [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'
```

View File

@ -0,0 +1,107 @@
---
title: How can I add a timeout to a promise in JavaScript?
shortTitle: Promise timeout
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,98 @@
---
title: How can I check for a blank value in JavaScript?
shortTitle: Value is blank
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,55 @@
---
title: Where and how can I use the Boolean function in JavaScript?
shortTitle: Boolean function use-cases
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,78 @@
---
title: Boolean traps and how to avoid them
shortTitle: Boolean traps
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,60 @@
---
title: A cautionary tale about JavaScript callbacks
shortTitle: Callback pitfalls
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,66 @@
---
title: How does JavaScript's prototypal inheritance differ from classical inheritance?
shortTitle: Prototypal vs classical inheritance
type: question
language: javascript
tags: [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';
```

55
snippets/js/s/closures.md Normal file
View File

@ -0,0 +1,55 @@
---
title: What are JavaScript closures?
shortTitle: Closures introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,67 @@
---
title: How can I clone an array in JavaScript?
shortTitle: Clone an array
type: question
language: javascript
tags: [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);
```

View File

@ -0,0 +1,43 @@
---
title: How do I compare two dates in JavaScript?
shortTitle: Date comparison
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,81 @@
---
title: How can I deep freeze an object in JavaScript?
shortTitle: Deep freeze object
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,71 @@
---
title: Where and how can I use the destructuring assignment syntax in JavaScript?
shortTitle: Destructuring assignment introduction
type: question
language: javascript
tags: [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;
```

View File

@ -0,0 +1,49 @@
---
title: How do I empty an array in JavaScript?
shortTitle: Empty an array
type: question
language: javascript
tags: [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();
```

View File

@ -0,0 +1,41 @@
---
title: What is the difference between encodeURI() and encodeURIComponent() in JavaScript?
shortTitle: encodeURI() vs encodeURIComponent()
type: question
language: javascript
tags: [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'
```

60
snippets/js/s/enum.md Normal file
View File

@ -0,0 +1,60 @@
---
title: How can I define an enum in JavaScript?
shortTitle: Enum implementation
type: question
language: javascript
tags: [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
```

55
snippets/js/s/equality.md Normal file
View File

@ -0,0 +1,55 @@
---
title: What is the difference between JavaScript's equality operators?
shortTitle: JavaScript equality operators
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,89 @@
---
title: Understanding event bubbling, capturing and delegation in JavaScript
shortTitle: Event bubbling, capturing and delegation
type: story
language: javascript
tags: [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
<html>
<body>
<div id="btn-container">
<button class="btn">Click me</button>
</div>
</body>
</html>
```
```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.

View File

@ -0,0 +1,117 @@
---
title: What is the Event Loop in JavaScript?
shortTitle: Event loop explained
type: question
language: javascript
tags: [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 its 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.

View File

@ -0,0 +1,69 @@
---
title: Are JavaScript closures inherently evil?
shortTitle: Closures and hidden state
type: story
language: javascript
tags: [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](/js/s/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.

View File

@ -0,0 +1,62 @@
---
title: How can I execute an event handler at most once?
shortTitle: Execute event handler only once
type: question
language: javascript
tags: [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
<button id="my-btn">Click me!</button>
```
```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
```

View File

@ -0,0 +1,27 @@
---
title: What is the difference between an expression and a statement in JavaScript?
shortTitle: Expressions and statements
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,55 @@
---
title: What is the difference between JavaScript's for...in, for...of and forEach?
shortTitle: JavaScript iteration methods comparison
type: question
language: javascript
tags: [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)
);
```

View File

@ -0,0 +1,47 @@
---
title: "Tip: Use JavaScript for loops if you need to break out early"
shortTitle: For loops for early breaking
type: tip
language: javascript
tags: [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
```

View File

@ -0,0 +1,66 @@
---
title: JavaScript function methods - call(), apply() and bind()
shortTitle: Function methods - call(), apply() and bind()
type: story
language: javascript
tags: [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
```

View File

@ -0,0 +1,68 @@
---
title: Using JavaScript generator functions for ranges
shortTitle: Generator functions for ranges
type: story
language: javascript
tags: [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
```

View File

@ -0,0 +1,31 @@
---
title: Understanding higher-order functions in JavaScript
shortTitle: Higher-order functions
type: story
language: javascript
tags: [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.

47
snippets/js/s/iife.md Normal file
View File

@ -0,0 +1,47 @@
---
title: What is an IIFE in JavaScript?
shortTitle: IIFE introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,26 @@
---
title: "Tip: Get the index of an array item in a JavaScript for...of loop"
shortTitle: Array index in for...of loops
type: tip
language: javascript
tags: [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](/js/s/for-in-for-of-foreach)._

View File

@ -0,0 +1,47 @@
---
title: How do I convert an iterable to an array in JavaScript?
shortTitle: Iterable to array
type: question
language: javascript
tags: [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]; // [ <!DOCTYPE html>, html ]
```
Note that the above example is the basis for the [nodeListToArray snippet](js/s/node-list-to-array).

View File

@ -0,0 +1,96 @@
---
title: What are JavaScript Iterators and where can I use them?
shortTitle: JavaScript iterators introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,58 @@
---
title: "Tip: Serialize specific properties from a JSON object"
shortTitle: Selective property serialization
type: tip
language: javascript
tags: [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" }'
```

View File

@ -0,0 +1,34 @@
---
title: "Tip: Make any JavaScript value iterable"
shortTitle: Make any value iterable
type: tip
language: javascript
tags: [array,iterator,generator]
author: chalarangelo
cover: rain-shopping
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]
```

View File

@ -0,0 +1,69 @@
---
title: Where and how can I use memoization in JavaScript?
shortTitle: Memoization introduction
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,58 @@
---
title: How do I merge two arrays in JavaScript?
shortTitle: Merge arrays
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,50 @@
---
title: How do I use JavaScript to modify the URL without reloading the page?
shortTitle: Modify URL without reloading
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,140 @@
---
title: JavaScript modules Cheat Sheet
type: cheatsheet
language: javascript
tags: [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.

View File

@ -0,0 +1,44 @@
---
title: JavaScript naming conventions
shortTitle: Naming conventions
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,59 @@
---
title: How can I use optional chaining and nullish coalescing in my JavaScript project?
shortTitle: Optional chaining and nullish coalescing
type: question
language: javascript
tags: [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)).

View File

@ -0,0 +1,31 @@
---
title: JavaScript's numeric separators explained
shortTitle: Numeric separators explained
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,125 @@
---
title: Can I use an object as an array without modifying it in JavaScript?
shortTitle: Object as array
type: question
language: javascript
tags: [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'
```

View File

@ -0,0 +1,70 @@
---
title: How do I compare two objects in JavaScript?
shortTitle: Object comparison
type: question
language: javascript
tags: [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).

View File

@ -0,0 +1,31 @@
---
title: What's the difference between Object.is() and the triple equals operator in JavaScript?
shortTitle: Object.is() vs triple equals operator
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,40 @@
---
title: Is JavaScript pass-by-value or pass-by-reference?
shortTitle: Pass-by-value or pass-by-reference
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,29 @@
---
title: What is the difference between prefix and postfix operators?
shortTitle: Prefix and postfix operators
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,59 @@
---
title: "Tip: Pretty-print a JSON object with JavaScript"
shortTitle: Pretty-print JSON
type: tip
language: javascript
tags: [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"
// }
```

View File

@ -0,0 +1,19 @@
---
title: "Tip: Prevent a string from being escaped in JavaScript"
shortTitle: Prevent string escaping
type: tip
language: javascript
tags: [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'
```

View File

@ -0,0 +1,52 @@
---
title: Is there a way to use instanceof for primitive JavaScript values?
shortTitle: Using instanceof for primitive values
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,26 @@
---
title: "Tip: The order of then and catch matters"
shortTitle: The order of then and catch matters
type: tip
language: javascript
tags: [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!

View File

@ -0,0 +1,47 @@
---
title: What is the difference between then and finally in a JavaScript promise?
shortTitle: Promise then vs finally
type: question
language: javascript
tags: [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.).

30
snippets/js/s/promises.md Normal file
View File

@ -0,0 +1,30 @@
---
title: What are promises in JavaScript? In which states can a promise be?
shortTitle: Promises introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,38 @@
---
title: JavaScript property enumerability
shortTitle: Property enumerability
type: story
language: javascript
tags: [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()`.

View File

@ -0,0 +1,36 @@
---
title: What is a pure function?
shortTitle: Pure function introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,21 @@
---
title: "Tip: Create your own query selector shorthand"
shortTitle: Query selector shorthand
type: tip
language: javascript
tags: [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"]');
```

View File

@ -0,0 +1,33 @@
---
title: Using random values with pure functions
shortTitle: Pure functions & randomness
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,28 @@
---
title: What is recursion and when is it useful?
shortTitle: Recursion introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,47 @@
---
title: How can I use JavaScript to reload the page?
shortTitle: Reload page
type: story
language: javascript
tags: [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.

View File

@ -0,0 +1,62 @@
---
title: How do I remove a property from a JavaScript object?
shortTitle: Remove property from object
type: question
language: javascript
tags: [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']
```

View File

@ -0,0 +1,59 @@
---
title: What does a JavaScript constructor return?
shortTitle: Constructor return value
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,52 @@
---
title: How do I clone an object in JavaScript?
shortTitle: Object cloning
type: question
language: javascript
tags: [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).

View File

@ -0,0 +1,55 @@
---
title: How can I implement a singleton in JavaScript?
shortTitle: Singleton implementation
type: question
language: javascript
tags: [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.

65
snippets/js/s/sleep.md Normal file
View File

@ -0,0 +1,65 @@
---
title: How can I implement a sleep function in JavaScript?
shortTitle: Sleep function
type: question
language: javascript
tags: [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)
```

View File

@ -0,0 +1,55 @@
---
title: Understanding the spread and rest syntax in Javascript
shortTitle: Spread and rest syntax
type: story
language: javascript
tags: [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]
```

View File

@ -0,0 +1,28 @@
---
title: "Tip: Minimize DOM access"
shortTitle: Minimize DOM access
type: tip
language: javascript
tags: [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.

View File

@ -0,0 +1,41 @@
---
title: Check if a string contains a substring in JavaScript
shortTitle: String contains substring
type: story
language: javascript
tags: [string]
author: chalarangelo
cover: cave-explorer
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
```

View File

@ -0,0 +1,21 @@
---
title: Are JavaScript strings immutable?
shortTitle: String immutability
type: question
language: javascript
tags: [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`.

View File

@ -0,0 +1,35 @@
---
title: "Tip: Convert a string to a boolean"
shortTitle: String to boolean
type: tip
language: javascript
tags: [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
```

View File

@ -0,0 +1,38 @@
---
title: "Tip: How to swap two variables in JavaScript"
shortTitle: Swap two variables
type: tip
language: javascript
tags: [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];
```

View File

@ -0,0 +1,110 @@
---
title: Replacing JavaScript switch statement with object literals
shortTitle: Switch with object literals
type: story
language: javascript
tags: [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'
```

View File

@ -0,0 +1,31 @@
---
title: What is the difference between synchronous and asynchronous code in JavaScript?
shortTitle: Synchronous vs asynchronous code
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,33 @@
---
title: 'Tip: Protect your users from malicious websites when using target="_blank"'
shortTitle: 'Safeguarding target="_blank"'
type: tip
language: javascript
tags: [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
<!-- Bad: susceptible to tabnabbing -->
<a href="https://externalresource.com/some-page" target="_blank">
External resource
</a>
<!-- Good: new tab cannot cause problems -->
<a
href="https://externalresource.com/some-page"
target="_blank"
rel="noopener noreferrer"
>
External resource
</a>
```
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.

View File

@ -0,0 +1,48 @@
---
title: What is the ternary operator and how do I use it?
shortTitle: Ternary operation introduction
type: question
language: javascript
tags: [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) => (
<h3>Item list{ count ? (<span> - {count} items</span>) : '(Empty)'}<h3>
);
```
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).

143
snippets/js/s/this.md Normal file
View File

@ -0,0 +1,143 @@
---
title: Understanding the "this" keyword in JavaScript
shortTitle: The "this" keyword in JavaScript
type: story
language: javascript
tags: [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'
```

View File

@ -0,0 +1,46 @@
---
title: What are truthy and falsy values in JavaScript?
shortTitle: Truthy and falsy values
type: question
language: javascript
tags: [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
```

View File

@ -0,0 +1,41 @@
---
title: What's the difference between undeclared, undefined and null in JavaScript?
shortTitle: Undeclared, undefined and null
type: question
language: javascript
tags: [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 (`===`).

115
snippets/js/s/use-strict.md Normal file
View File

@ -0,0 +1,115 @@
---
title: What does 'use strict' do and what are some of the key benefits to using it?
shortTitle: Strict mode introduction
type: question
language: javascript
tags: [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

View File

@ -0,0 +1,26 @@
---
title: "Tip: You can get the value of an input element as a number"
shortTitle: Input element value as number
type: tip
language: javascript
tags: [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.

View File

@ -0,0 +1,29 @@
---
title: What is the only value not equal to itself in JavaScript?
shortTitle: The only value not equal to itself
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,81 @@
---
title: What are the differences between var, let and const in JavaScript?
shortTitle: Var, let and const
type: question
language: javascript
tags: [type,variable]
author: chalarangelo
cover: green-css
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](/js/s/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](/js/s/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](/js/s/use-strict).

View File

@ -0,0 +1,71 @@
---
title: What is hoisting in JavaScript?
shortTitle: Hoisting introduction
type: question
language: javascript
tags: [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.

View File

@ -0,0 +1,31 @@
---
title: Understanding JavaScript variables and scopes
shortTitle: Variables and scopes
type: story
language: javascript
tags: [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.
![Visualization of JavaScript variable scope](./illustrations/js-variable-scope.png)
### 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.

View File

@ -0,0 +1,19 @@
---
title: "Tip: Avoid \"javascript:void(0)\" for empty links"
shortTitle: Avoid "javascript:void(0)" for empty links
type: tip
language: javascript
tags: [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 `<button>`, `<div>` or `<span>` 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.