diff --git a/README.md b/README.md
index 24de009..c2b9155 100644
--- a/README.md
+++ b/README.md
@@ -1064,7 +1064,7 @@ The main difference lies in the bubbling behavior of `mouseenter` and `mouseover
`mouseenter` events do not bubble. The `mouseenter` event is triggered only when the mouse pointer enters the element itself, not its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseenter` event will not be triggered on the parent element again, it's only triggered once upon entry of parent element without regard for its contents. If both parent and child have `mouseenter` listeners attached and the mouse pointer moves from the parent element to the child element, `mouseenter` will only fire for the child.
-`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If have a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
+`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
| Property | `mouseenter` | `mouseover` |
| --- | --- | --- |
@@ -4921,7 +4921,7 @@ The main difference lies in the bubbling behavior of `mouseenter` and `mouseover
`mouseenter` events do not bubble. The `mouseenter` event is triggered only when the mouse pointer enters the element itself, not its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseenter` event will not be triggered on the parent element again, it's only triggered once upon entry of parent element without regard for its contents. If both parent and child have `mouseenter` listeners attached and the mouse pointer moves from the parent element to the child element, `mouseenter` will only fire for the child.
-`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If have a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
+`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
| Property | `mouseenter` | `mouseover` |
| --- | --- | --- |
diff --git a/questions/describe-event-bubbling/en-US.mdx b/questions/describe-event-bubbling/en-US.mdx
index 71d1d0f..3ca9bb1 100644
--- a/questions/describe-event-bubbling/en-US.mdx
+++ b/questions/describe-event-bubbling/en-US.mdx
@@ -85,7 +85,7 @@ child.click();
## Event delegation
-Event bubbling is the basis for a technique called [event delegation](/questions/quiz/describe-event-delegation), where you attach a single event handler to a common ancestor of multiple elements and use event delegation to handle events for those elements efficiently. This is particularly useful when you have a large number of similar elements, like a list of items, and you want to avoid attaching individual event handlers to each item.
+Event bubbling is the basis for a technique called [event delegation](/questions/quiz/explain-event-delegation), where you attach a single event handler to a common ancestor of multiple elements and use event delegation to handle events for those elements efficiently. This is particularly useful when you have a large number of similar elements, like a list of items, and you want to avoid attaching individual event handlers to each item.
```js
parent.addEventListener('click', (event) => {
diff --git a/questions/explain-event-delegation/en-US.mdx b/questions/explain-event-delegation/en-US.mdx
index 0a0e0fb..29666bb 100644
--- a/questions/explain-event-delegation/en-US.mdx
+++ b/questions/explain-event-delegation/en-US.mdx
@@ -108,7 +108,7 @@ userForm.addEventListener('input', (event) => {
});
```
-In this example, a single input event listener is attached to the form element. It can respond to input changes for all child input elements, simplifying the code by an event listeners per `` element.
+In this example, a single input event listener is attached to the form element. It can respond to input changes for all child input elements, simplifying the code by eliminating the need for individual listeners on each `` element.
## Pitfalls
diff --git a/questions/explain-hoisting/en-US.mdx b/questions/explain-hoisting/en-US.mdx
index 6a317c6..2f1cef3 100644
--- a/questions/explain-hoisting/en-US.mdx
+++ b/questions/explain-hoisting/en-US.mdx
@@ -140,4 +140,4 @@ ESLint is a static code analyzer that can find violations of such cases with the
## Further reading
- [Hoisting | MDN](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
-- [JavaScript Visualized: Hoisting](https://dev.to/lydiahallie/javascript-visualized-hoisting-478h)
+- [What is Hoisting in JavaScript?](https://www.freecodecamp.org/news/what-is-hoisting-in-javascript)
diff --git a/questions/explain-the-concept-of-a-callback-function-in-asynchronous-operations/en-US.mdx b/questions/explain-the-concept-of-a-callback-function-in-asynchronous-operations/en-US.mdx
index 296499e..2263a67 100644
--- a/questions/explain-the-concept-of-a-callback-function-in-asynchronous-operations/en-US.mdx
+++ b/questions/explain-the-concept-of-a-callback-function-in-asynchronous-operations/en-US.mdx
@@ -96,4 +96,4 @@ fetchData((error, data) => {
- [MDN Web Docs: Callback function](https://developer.mozilla.org/en-US/docs/Glossary/Callback_function)
- [JavaScript.info: Callbacks](https://javascript.info/callbacks)
-- [Node.js: Asynchronous programming and callbacks](https://nodejs.org/en/knowledge/getting-started/control-flow/what-are-callbacks/)
+- [Node.js: Asynchronous programming and callbacks](https://nodejs.org/en/learn/asynchronous-work/javascript-asynchronous-programming-and-callbacks)
diff --git a/questions/how-do-you-abort-a-web-request-using-abortcontrollers/en-US.mdx b/questions/how-do-you-abort-a-web-request-using-abortcontrollers/en-US.mdx
index f7c7338..2986dd6 100644
--- a/questions/how-do-you-abort-a-web-request-using-abortcontrollers/en-US.mdx
+++ b/questions/how-do-you-abort-a-web-request-using-abortcontrollers/en-US.mdx
@@ -153,7 +153,7 @@ In situations where the user has navigated away from the page, aborting the requ
## Notes
- `AbortController`s is not `fetch()`-specific, it can be used to abort other asynchronous tasks as well.
-- A singular `AbortContoller` instance can be reused or multiple async tasks and cancel all of them at once.
+- A singular `AbortContoller` instance can be reused on multiple async tasks and cancel all of them at once.
- Calling `abort()` on `AbortController`s does not send any notification or signal to the server. The server is unaware of the cancelation and will continue processing the request until it completes or times out.
## Further reading
diff --git a/questions/how-do-you-handle-errors-in-asynchronous-operations/en-US.mdx b/questions/how-do-you-handle-errors-in-asynchronous-operations/en-US.mdx
index 730eda1..d9c271f 100644
--- a/questions/how-do-you-handle-errors-in-asynchronous-operations/en-US.mdx
+++ b/questions/how-do-you-handle-errors-in-asynchronous-operations/en-US.mdx
@@ -58,28 +58,33 @@ fetchData(); // Error fetching data: ....
If you have multiple asynchronous operations, you can nest `try...catch` blocks to handle errors at different levels.
```js live
-async function fetchData() {
- try {
- // Invalid URl
- const response = await fetch('https://api.example.com/data');
- const data = await response.json();
- console.log(data);
- } catch (error) {
- console.error('Error fetching data:', error);
- }
+async function fetchUser() {
+ // Simulate a successful async operation
+ return { id: 1, name: 'Alice' };
}
-async function processData() {
+async function fetchUserPosts() {
+ // Simulate a failed async operation
+ throw new Error('Failed to fetch posts');
+}
+
+async function loadUserData() {
try {
- await fetchData();
- // Additional processing
- console.log(arr); // Trying to reference an undefined variable will throw an error
- } catch (error) {
- console.error('Error processing data:', error);
+ const user = await fetchUser();
+ console.log('User:', user);
+
+ try {
+ const posts = await fetchUserPosts();
+ console.log('Posts:', posts);
+ } catch (postsError) {
+ console.error('Error fetching posts:', postsError.message);
+ }
+ } catch (userError) {
+ console.error('Error fetching user:', userError.message);
}
}
-processData();
+loadUserData();
```
## Using `.catch()` with Promises
diff --git a/questions/how-do-you-validate-form-elements-using-the-constraint-validation-api/en-US.mdx b/questions/how-do-you-validate-form-elements-using-the-constraint-validation-api/en-US.mdx
index a9666f6..6330ac7 100644
--- a/questions/how-do-you-validate-form-elements-using-the-constraint-validation-api/en-US.mdx
+++ b/questions/how-do-you-validate-form-elements-using-the-constraint-validation-api/en-US.mdx
@@ -115,4 +115,4 @@ In this example, the form will not submit if the `username` input is empty, and
- [MDN Web Docs: Constraint Validation](https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Constraint_validation)
- [MDN Web Docs: HTMLFormElement.checkValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/checkValidity)
-- [MDN Web Docs: HTMLFormElement.setCustomValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/setCustomValidity)
+- [MDN Web Docs: HTMLObjectElement.setCustomValidity()](https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/setCustomValidity)
diff --git a/questions/what-are-iterators-and-generators-and-what-are-they-used-for/en-US.mdx b/questions/what-are-iterators-and-generators-and-what-are-they-used-for/en-US.mdx
index 835bb5e..ff36c9a 100644
--- a/questions/what-are-iterators-and-generators-and-what-are-they-used-for/en-US.mdx
+++ b/questions/what-are-iterators-and-generators-and-what-are-they-used-for/en-US.mdx
@@ -179,7 +179,7 @@ In JavaScript, several built-in objects implement the iterator protocol, meaning
Generators are a special kind of function that can pause and resume their execution, allowing them to generate a sequence of values on-the-fly. They are commonly used to create iterators but have other applications as well. The key use cases of generators include:
-- Creating iterators is a more concise and readable way compared to manually implementing the iterator protocol.
+- Creating iterators in a more concise and readable way compared to manually implementing the iterator protocol.
- Implementing lazy evaluation, where values are generated only when needed, saving memory and computation time.
- Simplifying asynchronous programming by allowing code to be written in a synchronous-looking style using `yield` and `await`.
diff --git a/questions/what-are-some-common-performance-bottlenecks-in-javascript-applications/en-US.mdx b/questions/what-are-some-common-performance-bottlenecks-in-javascript-applications/en-US.mdx
index fa9eb21..98ba78b 100644
--- a/questions/what-are-some-common-performance-bottlenecks-in-javascript-applications/en-US.mdx
+++ b/questions/what-are-some-common-performance-bottlenecks-in-javascript-applications/en-US.mdx
@@ -38,16 +38,22 @@ Layout thrashing occurs when you read and write to the DOM repeatedly, causing m
```js
// Inefficient
-for (let i = 0; i < 1000; i++) {
- const height = element.clientHeight;
- element.style.height = `${height + 10}px`;
-}
+boxes.forEach((box) => {
+ const height = box.offsetHeight; // Read
+ box.style.height = `${height + 10}px`; // Write
+});
// Efficient
-const height = element.clientHeight;
-for (let i = 0; i < 1000; i++) {
- element.style.height = `${height + 10}px`;
-}
+// Batch read
+const heights = [];
+boxes.forEach((box) => {
+ heights.push(box.offsetHeight);
+});
+
+// Batch write
+boxes.forEach((box, i) => {
+ box.style.height = `${heights[i] + 10}px`;
+});
```
## Excessive use of global variables
diff --git a/questions/what-are-the-differences-between-xmlhttprequest-and-fetch/en-US.mdx b/questions/what-are-the-differences-between-xmlhttprequest-and-fetch/en-US.mdx
index 68b2e8e..312db6f 100644
--- a/questions/what-are-the-differences-between-xmlhttprequest-and-fetch/en-US.mdx
+++ b/questions/what-are-the-differences-between-xmlhttprequest-and-fetch/en-US.mdx
@@ -224,7 +224,7 @@ xhr.upload.onprogress = (event) => {
The callback assigned to `onprogress` is passed a [`ProgressEvent`](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/progress_event):
- The `loaded` field on the `ProgressEvent` is a 64-bit integer indicating the amount of work already performed (bytes uploaded/downloaded) by the underlying process.
-- The `total` field on the `ProgressEvent` is a 64-bit integer representing the total amount of work that the underlying process is in the progress of performing. When downloading resources, this is the `Content-Length` value of the HTTP request.
+- The `total` field on the `ProgressEvent` is a 64-bit integer representing the total amount of work that the underlying process is in the progress of performing. When downloading resources, this is the `Content-Length` value of the HTTP response.
On the other hand, the `fetch()` API does not offer any convenient way to track upload progress. It can be implemented by monitoring the `body` of the `Response` object as a fraction of the `Content-Length` header, but it's quite complicated.
diff --git a/questions/what-are-the-pros-and-cons-of-using-promises-instead-of-callbacks/en-US.mdx b/questions/what-are-the-pros-and-cons-of-using-promises-instead-of-callbacks/en-US.mdx
index 15a2a50..5d2514e 100644
--- a/questions/what-are-the-pros-and-cons-of-using-promises-instead-of-callbacks/en-US.mdx
+++ b/questions/what-are-the-pros-and-cons-of-using-promises-instead-of-callbacks/en-US.mdx
@@ -115,13 +115,49 @@ function getData3() {
Promise.all([getData1(), getData2(), getData3()])
.then((results) => {
- console.log(results); // Output: [[{ id: 1, title: 'Data 1' }, { id: 2, title: 'Data 2' }, { id: 3, title: 'Data 3' }]
+ console.log(results); // Output: [{ id: 1, title: 'Data 1' }, { id: 2, title: 'Data 2' }, { id: 3, title: 'Data 3' }]
})
.catch((error) => {
console.error('Error:', error);
});
```
+### Easier error handling with `.catch()` and guaranteed cleanup with `.finally()`
+
+Promises make error handling more straightforward by allowing you to catch errors at the end of a chain using `.catch()`, instead of manually checking for errors in every callback. This leads to cleaner and more maintainable code.
+
+Additionally, `.finally()` lets you run code after the Promise settles, whether it was successful or failed, which is great for cleanup tasks like hiding spinners or resetting UI states.
+
+```js live
+function getFirstData() {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({ id: 1, title: 'First Data' });
+ }, 1000);
+ });
+}
+
+function getSecondData(data) {
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve({ id: data.id, title: data.title + ' -> Second Data' });
+ }, 1000);
+ });
+}
+
+getFirstData()
+ .then(getSecondData)
+ .then((data) => {
+ console.log('Success:', data);
+ })
+ .catch((error) => {
+ console.error('Error:', error);
+ })
+ .finally(() => {
+ console.log('This runs no matter what');
+ });
+```
+
### With promises, these scenarios which are present in callbacks-only coding, will not happen:
- Call the callback too early
diff --git a/questions/what-is-the-definition-of-a-higher-order-function/en-US.mdx b/questions/what-is-the-definition-of-a-higher-order-function/en-US.mdx
index 7c6dcdd..bc1fe05 100644
--- a/questions/what-is-the-definition-of-a-higher-order-function/en-US.mdx
+++ b/questions/what-is-the-definition-of-a-higher-order-function/en-US.mdx
@@ -58,7 +58,7 @@ function greetName(greeter, name) {
greetName(greet, 'Alice'); // Output: Hello, Alice!
```
-In this example, the `greetName` function takes another function `greet` as an argument and executes it with the name `Alice`. The `greet` function is a higher-order function because it is passed as an argument to another function.
+In this example, the `greetName` function is higher-order function because it takes another function (`greet`) as an argument and uses it to generate a greeting for the given name.
### Functions as return values
diff --git a/questions/what-is-the-difference-between-double-equal-and-triple-equal/en-US.mdx b/questions/what-is-the-difference-between-double-equal-and-triple-equal/en-US.mdx
index 098fc79..5942d15 100644
--- a/questions/what-is-the-difference-between-double-equal-and-triple-equal/en-US.mdx
+++ b/questions/what-is-the-difference-between-double-equal-and-triple-equal/en-US.mdx
@@ -77,7 +77,7 @@ There's one final value-comparison operation within JavaScript, that is the [`Ob
## Conclusion
-- Use `==` when you want to compare values with type coercion (and understand the implications of it). Practically, the only valid use case for the equality operator is when against `null` and `undefined` for convenience.
+- Use `==` when you want to compare values with type coercion (and understand the implications of it). In practice, the only reasonable use case for the equality operator is to check for both `null` and `undefined` in a single comparison for convenience.
- Use `===` when you want to ensure both the value and the type are the same, which is the safer and more predictable choice in most cases.
### Notes
diff --git a/questions/what-is-the-difference-between-mouseenter-and-mouseover-event/en-US.mdx b/questions/what-is-the-difference-between-mouseenter-and-mouseover-event/en-US.mdx
index cab8bdc..acb8dfd 100644
--- a/questions/what-is-the-difference-between-mouseenter-and-mouseover-event/en-US.mdx
+++ b/questions/what-is-the-difference-between-mouseenter-and-mouseover-event/en-US.mdx
@@ -8,7 +8,7 @@ The main difference lies in the bubbling behavior of `mouseenter` and `mouseover
`mouseenter` events do not bubble. The `mouseenter` event is triggered only when the mouse pointer enters the element itself, not its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseenter` event will not be triggered on the parent element again, it's only triggered once upon entry of parent element without regard for its contents. If both parent and child have `mouseenter` listeners attached and the mouse pointer moves from the parent element to the child element, `mouseenter` will only fire for the child.
-`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If have a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
+`mouseover` events bubble up the DOM tree. The `mouseover` event is triggered when the mouse pointer enters the element or one of its descendants. If a parent element has child elements, and the mouse pointer enters child elements, the `mouseover` event will be triggered on the parent element again as well. If the parent element has multiple child elements, this can result in multiple event callbacks fired. If there are child elements, and the mouse pointer moves from the parent element to the child element, `mouseover` will fire for both the parent and the child.
| Property | `mouseenter` | `mouseover` |
| --- | --- | --- |
diff --git a/questions/whats-the-difference-between-a-variable-that-is-null-undefined-or-undeclared-how-would-you-go-about-checking-for-any-of-these-states/en-US.mdx b/questions/whats-the-difference-between-a-variable-that-is-null-undefined-or-undeclared-how-would-you-go-about-checking-for-any-of-these-states/en-US.mdx
index d3837ba..fa13442 100644
--- a/questions/whats-the-difference-between-a-variable-that-is-null-undefined-or-undeclared-how-would-you-go-about-checking-for-any-of-these-states/en-US.mdx
+++ b/questions/whats-the-difference-between-a-variable-that-is-null-undefined-or-undeclared-how-would-you-go-about-checking-for-any-of-these-states/en-US.mdx
@@ -34,7 +34,7 @@ console.log(typeof y === 'undefined'); // true
## `undefined`
-A variable that is `undefined` is a variable that has been declared, but not assigned a value. It is of type `undefined`. If a function does not return any value as the result of executing it is assigned to a variable, the variable also has the value of `undefined`. To check for it, compare using the strict equality (`===`) operator or `typeof` which will give the `'undefined'` string. Note that you should not be using the loose equality operator (`==`) to check, as it will also return `true` if the value is `null`.
+A variable that is `undefined` is a variable that has been declared, but not assigned a value. It is of type `undefined`. If a function does not return a value, and its result is assigned to a variable, that variable will also have the value `undefined`. To check for it, compare using the strict equality (`===`) operator or `typeof` which will give the `'undefined'` string. Note that you should not be using the loose equality operator (`==`) to check, as it will also return `true` if the value is `null`.
```js live
let foo;
diff --git a/questions/whats-the-difference-between-call-and-apply/en-US.mdx b/questions/whats-the-difference-between-call-and-apply/en-US.mdx
index 8b08c46..196d704 100644
--- a/questions/whats-the-difference-between-call-and-apply/en-US.mdx
+++ b/questions/whats-the-difference-between-call-and-apply/en-US.mdx
@@ -80,7 +80,7 @@ const person1 = { name: 'John' };
const person2 = { name: 'Alice' };
greet.call(person1); // Hello, my name is John
-greet.call(person2); // Hello, my name is Alice
+greet.apply(person2); // Hello, my name is Alice
```
### Alternative syntax to call methods on objects