quiz: remove JS questions

This commit is contained in:
Yangshun 2024-06-27 17:56:36 +08:00
parent 0d59986564
commit 27b7c68471
238 changed files with 0 additions and 10390 deletions

View File

@ -1,37 +0,0 @@
---
title: Can you describe the main difference between a `.forEach` loop and a `.map()` loop?
subtitle: Why you would pick one versus the other?
---
To understand the differences between the two, let's look at what each function does.
## `forEach`
- Iterates through the elements in an array.
- Executes a callback for each element.
- Does not return a value.
```js
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
// Do something with num and/or index.
});
// doubled = undefined
```
## `map`
- Iterates through the elements in an array.
- "Maps" each element to a new element by calling the function on each element, creating a new array as a result.
```js
const a = [1, 2, 3];
const doubled = a.map((num) => {
return num * 2;
});
// doubled = [2, 4, 6]
```
The main difference between `.forEach` and `.map()` is that `.map()` returns a new array. If you need the result, but do not wish to mutate the original array, `.map()` is the clear choice. If you simply need to iterate over an array, `forEach` is a fine choice.

View File

@ -1,11 +0,0 @@
{
"slug": "can-you-describe-the-main-difference-between-a-foreach-loop-and-a-map-loop-and-why-you-would-pick-one-versus-the-other",
"languages": [],
"companies": ["twitter"],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "easy"
}

View File

@ -1,37 +0,0 @@
---
title: Você pode descrever a principal diferença entre um loop `.forEach` e um loop `.map()`?
subtitle: Por que você escolheria um em vez do outro?
---
Para entender as diferenças entre os dois, vamos ver o que cada função faz.
## `forEach`
- Itera através dos elementos em uma matriz.
- Executa um callback para cada elemento.
- Não retorna um valor.
```js
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
// Faça algo com num e/ou índice.
});
// doubled = undefined
```
## `map`
- Itera através dos elementos em uma matriz.
- "Mapeia" cada elemento para um novo elemento chamando a função em cada elemento, criando um novo array como resultado.
```js
const a = [1, 2, 3];
const doubled = a.map((num) => {
return num * 2;
});
// duplicou = [2, 4, 6]
```
A principal diferença entre `.forEach` e `.map()` é que `.map()` retorna um novo array. Se você precisa do resultado, mas não deseja alterar o array original, `.map()` é a opção clara. Se você simplesmente precisa iterar sobre um array, `forEach` é uma ótima escolha.

View File

@ -1,37 +0,0 @@
---
title: 你能描述一个 `.forEach` 循环和 `.map()` 循环之间的主要差异吗?
subtitle: 这两者你会如何选择?
---
为了理解两者之间的差异,让我们看看每个函数做什么。
## `forEach`
- 通过数组中的元素进行迭代。
- 对每个元素执行回调。
- 不返回值。
```js
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
// 使用 num 和 index 做点什么
});
// doubled = undefined
```
## `map`
- 通过数组中的元素进行迭代。
- 通过在每个元素上调用函数,将每个元素 "映射 "到一个新的元素上,并作为结果创建一个新的数组。
```js
const a = [1, 2, 3];
const doubled = a.map((num) => {
return num * 2;
});
// doubled = [2, 4, 6]
```
`.forEach` 和 `.map()` 之间的主要区别是`.map()` 返回一个新数组。 如果你需要结果,但不想改变原始数组,`.map()`是一个明确的选择。 如果你只需遍历一个数组,`forEach`就是一个很好的选择。

View File

@ -1,38 +0,0 @@
---
title: Can you give an example for destructuring an object or an array?
---
Destructuring is an expression available in ES2015 which enables a succinct and convenient way to extract values of Objects or Arrays and place them into distinct variables.
## Array destructuring
```js
// Variable assignment.
const foo = ['one', 'two', 'three'];
const [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
```
```js
// Swapping variables
let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
```
## Object destructuring
```js
// Variable assignment.
const o = { p: 42, q: true };
const { p, q } = o;
console.log(p); // 42
console.log(q); // true
```

View File

@ -1,11 +0,0 @@
{
"slug": "can-you-give-an-example-for-destructuring-an-object-or-an-array",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "easy"
}

View File

@ -1,38 +0,0 @@
---
title: Você pode dar um exemplo para desestruturar um objeto ou um array?
---
Destructuring é uma expressão disponível no ES2015 que permite uma maneira sucinta e conveniente de extrair valores de objetos ou arrays e colocá-los em variáveis distintas.
## Desestruturação de array
```js
// Atribuição de variáveis.
const foo = ['one', 'two', 'three'];
const [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
```
```js
// Trocar variáveis
let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
```
## Desestruturação de objeto
```js
// Atribuição de variáveis.
const o = { p: 42, q: true };
const { p, q } = o;
console.log(p); // 42
console.log(q); // true
```

View File

@ -1,38 +0,0 @@
---
title: 您能提供一个解构对象或数组的例子吗?
---
解构是一个在 ES2015 中可用的表达式,它使得能够以简洁和方便的方式提取对象或数组的值,并将它们置于不同的变量中。
## 数组的解构
```js
// 变量赋值
const foo = ['one', 'two', 'three'];
const [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
```
```js
// 交换变量
let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a); // 3
console.log(b); // 1
```
## 对象的解构
```js
// 变量赋值
const o = { p: 42, q: true };
const { p, q } = o;
console.log(p); // 42
console.log(q); // true
```

View File

@ -1,33 +0,0 @@
---
title: Can you give an example of a curry function and why this syntax offers an advantage?
---
Currying is a pattern where a function with more than one parameter is broken into multiple functions that, when called in series, will accumulate all of the required parameters one at a time. This technique can be useful for making code written in a functional style easier to read and compose. It's important to note that for a function to be curried, it needs to start out as one function, then broken out into a sequence of functions that each accepts one parameter.
```js
function curry(fn) {
if (fn.length === 0) {
return fn;
}
function _curried(depth, args) {
return function (newArgument) {
if (depth - 1 === 0) {
return fn(...args, newArgument);
}
return _curried(depth - 1, [...args, newArgument]);
};
}
return _curried(fn.length, []);
}
function add(a, b) {
return a + b;
}
var curriedAdd = curry(add);
var addFive = curriedAdd(5);
var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]
```

View File

@ -1,11 +0,0 @@
{
"slug": "can-you-give-an-example-of-a-curry-function-and-why-this-syntax-offers-an-advantage",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "medium"
}

View File

@ -1,33 +0,0 @@
---
title: Você pode dar um exemplo de uma função de curry e por que essa sintaxe oferece uma vantagem?
---
Currying é um padrão em que uma função com mais de um parâmetro é dividida em várias funções que, quando chamadas em série, acumularão todos os parâmetros necessários um de cada vez. Essa técnica pode ser útil para tornar o código escrito em um estilo funcional mais fácil de ler e compor. É importante observar que, para que uma função seja curried, ela precisa começar como uma função e, em seguida, ser dividida em uma sequência de funções que cada uma aceita um parâmetro.
```js
function curry(fn) {
if (fn.length === 0) {
return fn;
}
function _curried(depth, args) {
return function (newArgument) {
if (depth - 1 === 0) {
return fn(...args, newArgument);
}
return _curried(depth - 1, [...args, newArgument]);
};
}
return _curried(fn.length, []);
}
function add(a, b) {
return a + b;
}
var curriedAdd = curry(add);
var addFive = curriedAdd(5);
var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]
```

View File

@ -1,33 +0,0 @@
---
title: 您能提供一个柯里化函数的例子,以及为什么这个语法会有优势?
---
柯里化是一种模式,即一个有多个参数的函数被分解成多个函数,当被串联调用时,将一次积累所有需要的参数。 这种技术有助于使以函数式风格的代码更容易阅读和组合。 值得注意的是,要使一个函数被柯里化,它需要从一个函数开始,然后分解成一连串的函数,每个函数接受一个参数。
```js
function curry(fn) {
if (fn.length === 0) {
return fn;
}
function _curried(depth, args) {
return function (newArgument) {
if (depth - 1 === 0) {
return fn(...args, newArgument);
}
return _curried(depth - 1, [...args, newArgument]);
};
}
return _curried(fn.length, []);
}
function add(a, b) {
return a + b;
}
var curriedAdd = curry(add);
var addFive = curriedAdd(5);
var result = [0, 1, 2, 3, 4, 5].map(addFive); // [5, 6, 7, 8, 9, 10]
```

View File

@ -1,50 +0,0 @@
---
title: Can you offer a use case for the new arrow => function syntax?
subtitle: How does this new syntax differ from other functions?
---
The `=>` function syntax, also known as "arrow functions," is a feature introduced in ECMAScript 6 (ES6) for JavaScript. It provides a more concise way to write functions and also has some differences in how `this` behaves compared to traditional function expressions. Here's a simple use case to illustrate its utility:
## Use case: filtering an array
Imagine you have an array of numbers, and you want to filter out all the numbers that are less than 10. Using traditional function syntax and the new arrow function syntax, you can achieve this in the following ways:
### Traditional functions syntax
```js
const numbers = [1, 5, 10, 15, 20];
const filteredNumbers = numbers.filter(function (number) {
return number >= 10;
});
console.log(filteredNumbers); // Output: [10, 15, 20]
```
### Arrow function syntax
```js
const numbers = [1, 5, 10, 15, 20];
const filteredNumbers = numbers.filter((number) => number >= 10);
console.log(filteredNumbers); // Output: [10, 15, 20]
```
## Advantages of arrow functions
1. **Conciseness**: Arrow functions are more concise, making your code shorter and easier to read.
1. **`this` Behavior**: Arrow functions do not have their own `this`. Instead, they inherit `this` from the parent scope at the time they are defined. This is particularly useful in scenarios where you are dealing with callbacks and want to retain the context of `this`.
1. **Implicit Return**: If the function body consists of a single expression, arrow functions allow you to omit the `return` keyword and the curly braces.
## When to use arrow functions
- When you need a quick, one-line function.
- In callback functions where you want to preserve the lexical scope of `this`.
- When working with higher-order functions like `map`, `filter`, `reduce`, etc.
## When not to use arrow functions
- **Methods in objects**: Arrow functions do not have their own `this` context, which can lead to unexpected behavior in object methods.
- **As constructors**: Arrow functions cannot be used as constructors and will throw an error if used with the `new` keyword.
- **When you need to use function hoisting**: Arrow functions are not hoisted, unlike traditional function declarations.
Arrow functions are a powerful addition to JavaScript, simplifying function syntax and addressing some common pitfalls associated with the `this` keyword in traditional functions. They are especially useful in modern JavaScript development patterns.

View File

@ -1,11 +0,0 @@
{
"slug": "can-you-offer-a-use-case-for-the-new-arrow-function-syntax-how-does-this-new-syntax-differ-from-other-functions",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,50 +0,0 @@
---
title: Você pode oferecer um caso de uso para a nova sintaxe de arrow function =>?
subtitle: Como essa nova sintaxe difere de outras funções?
---
A sintaxe de função `=>`, também conhecida como "funções de seta", é um recurso introduzido no ECMAScript 6 (ES6) para o JavaScript. Ela fornece uma maneira mais concisa de escrever funções e também apresenta algumas diferenças em relação ao comportamento do `this` em comparação com expressões de função tradicionais. Aqui está um caso de uso simples para ilustrar sua utilidade:
## Caso de Uso: filtrando um array
Imagine que você tenha um array de números e queira filtrar todos os números menores que 10. Usando a sintaxe de função tradicional e a nova sintaxe de função de seta, você pode realizar isso das seguintes maneiras:
### Sintaxe de função tradicional
```js
const numbers = [1, 5, 10, 15, 20];
const numbersFiltrados = numbers.filter(function (number) {
return number >= 10;
});
console.log(numbersFiltrados); // Saída: [10, 15, 20]
```
### Sintaxe de função de seta
```js
const numbers = [1, 5, 10, 15, 20];
const numbersFiltrados = numbers.filter((number) => number >= 10);
console.log(numbersFiltrados); // Saída: [10, 15, 20]
```
## Vantagens das funções de seta
1. **Concisão**: As funções de seta são mais concisas, tornando seu código mais curto e mais fácil de ler.
1. **Comportamento do `this`**: As funções de seta não possuem seu próprio `this`. Em vez disso, elas herdam o `this` do escopo pai no momento em que são definidas. Isso é particularmente útil em cenários em que você está lidando com callbacks e deseja manter o contexto do `this`.
1. **Retorno Implícito**: Se o corpo da função consistir em uma única expressão, as funções de seta permitem omitir a palavra-chave `return` e as chaves.
## Quando usar funções de seta
- Quando você precisa de uma função rápida de uma única linha.
- Em funções de retorno de chamada (callbacks) onde você deseja preservar o escopo léxico do `this`.
- Ao trabalhar com funções de ordem superior como `map`, `filter`, `reduce`, etc.
## Quando não usar funções de seta
- **Métodos em objetos**: As funções de seta não têm seu próprio contexto `this`, o que pode levar a comportamentos inesperados em métodos de objetos.
- **Como construtores**: As funções de seta não podem ser usadas como construtores e gerarão um erro se usadas com a palavra-chave `new`.
- **Quando você precisa de hoisting de função**: As funções de seta não são içadas (hoisted), ao contrário das declarações de função tradicionais.
As funções de seta são uma adição poderosa ao JavaScript, simplificando a sintaxe das funções e abordando algumas armadilhas comuns associadas à palavra-chave `this` em funções tradicionais. Elas são especialmente úteis nos padrões de desenvolvimento JavaScript modernos.

View File

@ -1,50 +0,0 @@
---
title: 您可以为新箭头函数语法提供一个用例吗?
subtitle: 这个新语法与其他函数有什么不同?
---
`=>` 函数语法,也被称为 "箭头函数",是在 ECMAScript 6ES6中引入的 JavaScript 功能。它提供了一种更简洁的编写函数的方式,并且在 `this` 的行为方面与传统函数表达式有一些不同。下面通过一个简单的用例来说明它的实用性:
## 用例:筛选数组
假设你有一个包含数字的数组,你想筛选出所有小于 10 的数字。你可以使用传统的函数语法和新的箭头函数语法来实现这一目标,如下所示:
### 传统函数语法
```js
const numbers = [1, 5, 10, 15, 20];
const filteredNumbers = numbers.filter(function (number) {
return number >= 10;
});
console.log(filteredNumbers); // 输出: [10, 15, 20]
```
### 箭头函数语法
```js
const numbers = [1, 5, 10, 15, 20];
const filteredNumbers = numbers.filter((number) => number >= 10);
console.log(filteredNumbers); // 输出: [10, 15, 20]
```
## 箭头函数的优点
1. **简洁性**:箭头函数更加简洁,使你的代码更短且易于阅读。
1. **`this` 行为**:箭头函数没有自己的 `this`。相反,它们继承自它们在定义时的父级作用域中的 `this`。这在处理回调并希望保留 `this` 上下文的情况下特别有用。
1. **隐式返回**:如果函数体只包含一个表达式,箭头函数允许省略 `return` 关键字和花括号。
## 何时使用箭头函数
- 当你需要一个快速的、单行的函数时。
- 在回调函数中,当你想要保留 `this` 的词法作用域时。
- 在使用 `map`、`filter`、`reduce` 等高阶函数时。
## 何时不要使用箭头函数
- **对象方法**:箭头函数没有自己的 `this` 上下文,在对象方法中可能会导致意外行为。
- **作为构造函数**:箭头函数不能作为构造函数使用,如果使用 `new` 关键字会引发错误。
- **当你需要使用函数提升**:与传统的函数声明不同,箭头函数不会提升。
箭头函数是 JavaScript 的一个强大补充,简化了函数语法,并解决了传统函数中 `this` 关键字的一些常见问题。它们在现代 JavaScript 开发模式中特别有用。

View File

@ -1,15 +0,0 @@
---
title: Create a for loop that iterates up to `100` while outputting **"fizz"** at multiples of `3`, **"buzz"** at multiples of `5` and **"fizzbuzz"** at multiples of `3` and `5`
---
Check out this version of FizzBuzz by [Paul Irish](https://gist.github.com/jaysonrowe/1592432#gistcomment-790724).
```js
for (let i = 1; i <= 100; i++) {
let f = i % 3 == 0,
b = i % 5 == 0;
console.log(f ? (b ? 'FizzBuzz' : 'Fizz') : b ? 'Buzz' : i);
}
```
It is not advisable to write the above during interviews though. Just stick with the long but clear approach. For more wacky versions of FizzBuzz, check out the reference link below.

View File

@ -1,11 +0,0 @@
{
"slug": "create-a-for-loop-that-iterates-up-to-100-while-outputting-fizz-at-multiples-of-3-buzz-at-multiples-of-5-and-fizzbuzz-at-multiples-of-3-and-5",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "easy"
}

View File

@ -1,15 +0,0 @@
---
title: Crie um loop for que itere até `100` enquanto exibe **"fizz"** em múltiplos de `3`, **"buzz"** em múltiplos de `5` e **"fizzbuzz"** em múltiplos de `3` e `5`
---
Confira esta versão de FizzBuzz por [Paul Irish](https://gist.github.com/jaysonrowe/1592432#gistcomment-790724).
```js
for (let i = 1; i <= 100; i++) {
let f = i % 3 == 0,
b = i % 5 == 0;
console.log(f ? (b ? 'FizzBuzz' : 'Fizz') : b ? 'Buzz' : i);
}
```
No entanto, não é aconselhável escrever isso acima durante entrevistas. Mantenha-se fiel à abordagem longa mas clara. Para mais versões malucas de FizzBuzz, confira o link de referência abaixo.

View File

@ -1,15 +0,0 @@
---
title: 创建一个for循环迭代到`100`,同时在`3`的倍数上输出**"fizz "**,在`5`的倍数上输出**"buzz"**,在`3`和`5`的公倍数上输出**"fizzbuzz"**。
---
看看这个版本的 FizzBuzz作者是 [Paul Irish](https://gist.github.com/jaysonrowe/1592432#gistcomment-790724)。
```js
for (let i = 1; i <= 100; i++) {
let f = i % 3 == 0,
b = i % 5 == 0;
console.log(f ? (b ? 'FizzBuzz' : 'Fizz') : b ? 'Buzz' : i);
}
```
不过,上述内容不宜在面试时写。 只要坚持长期而明确的做法。 关于更多古怪的 FizzBuzz 版本,请查看下面的参考链接。

View File

@ -1,192 +0,0 @@
---
title: Describe event bubbling
---
## TL;DR
Event bubbling is a DOM event propagation mechanism where an event (e.g. a click), starts at the target element and bubbles up to the root of the document. This allows ancestor elements to also respond to the event.
Event bubbling is essential for event delegation, where a single event handler manages events for multiple child elements, enhancing performance and code simplicity. While convenient, failing to manage event propagation properly can lead to unintended behavior, such as multiple handlers firing for a single event.
---
## What is event bubbling?
Event bubbling is a propagation mechanism in the DOM (Document Object Model) where an event, such as a click or a keyboard event, is first triggered on the target element that initiated the event and then propagates upward (bubbles) through the DOM tree to the root of the document.
**Note**: even before the event bubbling phase happens is the [event capturing](/questions/quiz/describe-event-capturing) phase which is the opposite of bubbling where the event goes down from the document root to the target element.
## Bubbling phase
During the bubbling phase, the event starts at the target element and bubbles up through its ancestors in the DOM hierarchy. This means that the event handlers attached to the target element and its ancestors can all potentially receive and respond to the event.
Here's an example using modern ES6 syntax to demonstrate event bubbling:
```js
// HTML:
// <div id="parent">
// <button id="child">Click me!</button>
// </div>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('click', () => {
console.log('Parent element clicked');
});
child.addEventListener('click', () => {
console.log('Child element clicked');
});
```
When you click the "Click me!" button, both the child and parent event handlers will be triggered due to the event bubbling.
## Stopping the bubbling
Event bubbling can be stopped during the bubbling phase using the `stopPropagation()` method. If an event handler calls `stopPropagation()`, it prevents the event from further bubbling up the DOM tree, ensuring that only the handlers of the elements up to that point in the hierarchy are executed.
```js
child.addEventListener('click', (event) => {
console.log('Child element clicked');
event.stopPropagation();
});
```
## 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.
```js
parent.addEventListener('click', (event) => {
if (event.target && event.target.id === 'child') {
console.log('Child element clicked');
}
});
```
## Benefits
- **Cleaner code:** Reduced number of event listeners improves code readability and maintainability.
- **Efficient event handling:** Minimizes performance overhead by attaching fewer listeners.
- **Flexibility:** Allows handling events happening on child elements without directly attaching listeners to them.
## Pitfalls
- **Accidental event handling:** Be mindful that parent elements might unintentionally capture events meant for children. Use `event.target` to identify the specific element that triggered the event.
- **Event order:** Events bubble up in a specific order. If multiple parents have event listeners, their order of execution depends on the DOM hierarchy.
- **Over-delegation:** While delegating events to a common ancestor is efficient, attaching a listener too high in the DOM tree might capture unintended events.
## Use cases
Here are some practical ways to use event bubbling to write better code.
### Reducing code with event delegation
Imagine you have a product list with numerous items, each with a "Buy Now" button. Traditionally, you might attach a separate click event listener to each button:
```js
// HTML:
// <ul id="product-list">
// <li><button id="item1-buy">Buy Now</button></li>
// <li><button id="item2-buy">Buy Now</button></li>
// </ul>
const item1Buy = document.getElementById('item1-buy');
const item2Buy = document.getElementById('item2-buy');
item1Buy.addEventListener('click', handleBuyClick);
item2Buy.addEventListener('click', handleBuyClick);
// ... repeat for each item ...
function handleBuyClick(event) {
console.log('Buy button clicked for item:', event.target.id);
}
```
This approach becomes cumbersome as the number of items grows. Here's how event bubbling can simplify things:
```js
// HTML:
// <ul id="product-list">
// <li><button id="item1-buy">Buy Now</button></li>
// <li><button id="item2-buy">Buy Now</button></li>
// </ul>
const productList = document.getElementById('product-list');
productList.addEventListener('click', handleBuyClick);
function handleBuyClick(event) {
// Check if the clicked element is a button within the list
if (event.target.tagName.toLowerCase() === 'button') {
console.log('Buy button clicked for item:', event.target.textContent);
}
}
```
By attaching the listener to the parent (`productList`) and checking the clicked element (`event.target`) within the handler, you achieve the same functionality with less code. This approach scales well when the items are dynamic as no new event handlers have to be added or removed when the list of items change.
### Dropdown menus
Consider a dropdown menu where clicking anywhere on the menu element (parent) should close it. With event bubbling, you can achieve this with a single listener:
```js
// HTML:
// <div id="dropdown">
// <button>Open Menu</button>
// <ul>
// <li>Item 1</li>
// <li>Item 2</li>
// </ul>
// </div>
const dropdown = document.getElementById('dropdown');
dropdown.addEventListener('click', handleDropdownClick);
function handleDropdownClick(event) {
// Close the dropdown if clicked outside the button
if (event.target !== dropdown.querySelector('button')) {
console.log('Dropdown closed');
// Your logic to hide the dropdown content
}
}
```
Here, the click event bubbles up from the clicked element (button or list item) to the `dropdown` element. The handler checks if the clicked element is not the `<button>` and closes the menu accordingly.
### Accordion menus
Imagine an accordion menu where clicking a section header (parent) expands or collapses the content section (child) below it. Event bubbling makes this straightforward:
```js
// HTML:
// <div class="accordion">
// <div class="header">Section 1</div>
// <div class="content">Content for Section 1</div>
// <div class="header">Section 2</div>
// <div class="content">Content for Section 2</div>
// </div>
const accordion = document.querySelector('.accordion');
accordion.addEventListener('click', handleAccordionClick);
function handleAccordionClick(event) {
// Check if clicked element is a header
if (event.target.classList.contains('header')) {
const content = event.target.nextElementSibling;
content.classList.toggle('active'); // Toggle display of content
}
}
```
By attaching the listener to the `accordion` element, clicking on any header triggers the event. The handler checks if the clicked element is a header and toggles the visibility of the corresponding content section.
## Further reading
- [MDN Web Docs on Event Bubbling](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
- [JavaScript.info - Bubbling and Capturing](https://javascript.info/bubbling-and-capturing)
- [W3C DOM Level 3 Events Specification](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)

View File

@ -1,11 +0,0 @@
{
"slug": "describe-event-bubbling",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "html"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,45 +0,0 @@
---
title: Descreva a propagação de eventos
---
A propagação de eventos é um mecanismo na DOM (Modelo de Objetos do Documento) em que um evento, como um clique ou um evento de teclado, é primeiro acionado no elemento de destino que iniciou o evento e, em seguida, se propaga para cima (bolhas) pela árvore da DOM até a raiz do documento.
## Fase de bolha
Durante a fase de bolha, o evento começa no elemento de destino e se propaga pelos seus ancestrais na hierarquia da DOM. Isso significa que os manipuladores de eventos associados ao elemento de destino e aos seus ancestrais podem potencialmente receber e responder ao evento.
Aqui está um exemplo usando a sintaxe moderna do ES6 para demonstrar a propagação de eventos:
```js
// HTML:
// <div id="pai">
// <button id="filho">Clique em mim!</button>
// </div>
const pai = document.getElementById('pai');
const filho = document.getElementById('filho');
pai.addEventListener('click', () => {
console.log('Cliquei no elemento pai');
});
filho.addEventListener('click', () => {
console.log('Cliquei no elemento filho');
});
```
Quando você clica no botão "Clique em mim!", devido à propagação de eventos, os manipuladores de eventos do filho e do pai serão acionados.
## Parando a propagação
A propagação de eventos pode ser interrompida durante a fase de bolha usando o método `stopPropagation()`. Se um manipulador de eventos chamar `stopPropagation()`, ele impedirá que o evento continue a se propagar pela árvore da DOM, garantindo que apenas os manipuladores dos elementos até aquele ponto na hierarquia sejam executados.
## Delegação de eventos
A propagação de eventos é a base para uma técnica chamada "delegação de eventos", onde você anexa um único manipulador de eventos a um ancestral comum de vários elementos e usa a delegação de eventos para lidar eficientemente com os eventos desses elementos. Isso é particularmente útil quando você tem um grande número de elementos semelhantes, como uma lista de itens, e deseja evitar a adição de manipuladores de eventos individuais a cada item.
## Referências
- [MDN Web Docs sobre Propagação de Eventos](https://developer.mozilla.org/pt-BR/docs/Web/API/Event/stopPropagation)
- [JavaScript.info - Bolhas e Captura](https://javascript.info/bubbling-and-capturing)
- [Especificação de Eventos do W3C DOM Nível 3](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)

View File

@ -1,45 +0,0 @@
---
title: 描述事件冒泡过程
---
事件冒泡是 DOM文档对象模型中的一种传播机制其中事件如点击或键盘事件首先在启动事件的目标元素上触发然后向上冒泡通过 DOM 树传播到文档的根部。
## 冒泡阶段
在冒泡阶段期间,事件从目标元素开始,并通过其在 DOM 层次结构中的祖先向上冒泡。这意味着附加到目标元素及其祖先的事件处理程序都有可能接收并响应事件。
以下是使用现代 ES6 语法演示事件冒泡的示例:
```js
// HTML:
// <div id="parent">
// <button id="child">点击我!</button>
// </div>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener('click', () => {
console.log('单击了父元素');
});
child.addEventListener('click', () => {
console.log('单击了子元素');
});
```
当单击 "点击我!" 按钮时,由于事件冒泡,子元素和父元素的事件处理程序都将被触发。
## 阻止传播
在冒泡阶段,可以使用 `stopPropagation()` 方法停止事件传播。如果事件处理程序调用 `stopPropagation()`,它将阻止事件继续向上冒泡到 DOM 树,确保只有位于层次结构中的元素的处理程序被执行。
## 事件委托
事件冒泡是一种称为 "事件委托" 的技术的基础,其中将单个事件处理程序附加到多个元素的共同祖先,并使用事件委托有效地处理这些元素的事件。当您有大量类似元素,例如项目列表时,希望避免为每个项目附加单独的事件处理程序时,这种方法特别有用。
## 参考资料
- [MDN Web Docs 上的事件冒泡](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling)
- [JavaScript.info - 冒泡和捕获](https://javascript.info/bubbling-and-capturing)
- [W3C DOM Level 3 事件规范](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)

View File

@ -1,96 +0,0 @@
---
title: Describe event capturing
---
## TL;DR
Event capturing is a lesser-used counterpart to [event bubbling](/questions/quiz/describe-event-bubbling) in the DOM event propagation mechanism. It follows the opposite order, where an event triggers first on the ancestor element and then travels down to the target element.
Event capturing is rarely used as compared to event bubbling, but it can be used in specific scenarios where you need to intercept events at a higher level before they reach the target element. It is disabled by default but can be enabled through an option on `addEventListener()`.
---
## What is event capturing?
Event capturing is a propagation mechanism in the DOM (Document Object Model) where an event, such as a click or a keyboard event, is first triggered at the root of the document and then flows down through the DOM tree to the target element.
Capturing has a higher priority than bubbling, meaning that capturing event handlers are executed before bubbling event handlers, as shown by the phases of event propagation:
- **Capturing phase**: The event moves down towards the target element
- **Target phase**: The event reaches the target element
- **Bubbling phase**: The event bubbles up from the target element
Note that event capturing is disabled by default. To enable it you have to pass the capture option into `addEventListener()`.
## Capturing phase
During the capturing phase, the event starts at the document root and propagates down to the target element. Any event listeners on ancestor elements in this path will be triggered before the target element's handler. But note that event capturing can't happen until the third argument of `addEventListener()` is set to `true` as shown below (default value is `false`).
Here's an example using modern ES2015 syntax to demonstrate event capturing:
```js
// HTML:
// <div id="parent">
// <button id="child">Click me!</button>
// </div>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener(
'click',
() => {
console.log('Parent element clicked (capturing)');
},
true, // Set third argument to true for capturing
);
child.addEventListener('click', () => {
console.log('Child element clicked');
});
```
When you click the "Click me!" button, it will trigger the parent element's capturing handler first, followed by the child element's handler.
## Stopping propagation
Event propagation can be stopped during the capturing phase using the `stopPropagation()` method. This prevents the event from traveling further down the DOM tree.
```js
// HTML:
// <div id="parent">
// <button id="child">Click me!</button>
// </div>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
parent.addEventListener(
'click',
(event) => {
console.log('Parent element clicked (capturing)');
event.stopPropagation(); // Stop event propagation
},
true,
);
child.addEventListener('click', () => {
console.log('Child element clicked');
});
```
As a result of stopping event propagation, just the `parent` event listener will now be called when you click the "Click Me!" button, and the `child` event listener will never be called because the event propagation has stopped at the `parent` element.
## Uses of event capturing
Event capturing is rarely used as compared to event bubbling, but it can be used in specific scenarios where you need to intercept events at a higher level before they reach the target element.
- **Stopping event bubbling:** Imagine you have a nested element (like a button) inside a container element. Clicking the button might also trigger a click event on the container. By using enabling event capturing on the container's event listener, you can capture the click event there and prevent it from traveling down to the button, potentially causing unintended behavior.
- **Custom dropdown menus:**: When building custom dropdown menus, you might want to capture clicks outside the menu element to close the menu. Using `capture: true` on the `document` object allows you to listen for clicks anywhere on the page and close the menu if the click happens outside its boundaries.
- **Efficiency in certain scenarios:**: In some situations, event capturing can be slightly more efficient than relying on bubbling. This is because the event doesn't need to propagate through all child elements before reaching the handler. However, the performance difference is usually negligible for most web applications.
## Further reading
- [Event Capturing | MDN](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_capture)
- [Bubbling and Capturing | JavaScript.info](https://javascript.info/bubbling-and-capturing)
- [W3C DOM Level 3 Events Specification](https://www.w3.org/TR/DOM-Level-3-Events/#event-flow)

View File

@ -1,11 +0,0 @@
{
"slug": "describe-event-capturing",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "html"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,146 +0,0 @@
---
title: Describe the difference between a cookie, `sessionStorage` and `localStorage`.
---
## TL;DR
All of the following are mechanisms of storing data on the client, the user's browser in this case. `localStorage` and `sessionStorage` both implement the [Web Storage API interface](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API).
- **Cookies**: Suitable for server-client communication, small storage capacity, can be persistent or session-based, domain-specific. Sent to the server on every request.
- **`localStorage`**: Suitable for long-term storage, data persists even after the browser is closed, accessible across all tabs and windows of the same origin, highest storage capacity among the three.
- **`sessionStorage`**: Suitable for temporary data within a single page session, data is cleared when the tab or window is closed, has a higher storage capacity compared to cookies.
Here's a table summarizing the 3 client storage mechanisms.
| Property | Cookie | `localStorage` | `sessionStorage` |
| --- | --- | --- | --- |
| Initiator | Client or server. Server can use `Set-Cookie` header | Client | Client |
| Lifespan | As specified | Until deleted | Until tab is closed |
| Persistent across browser sessions | If a future expiry date is set | Yes | No |
| Sent to server with every HTTP request | Yes, sent via `Cookie` header | No | No |
| Total capacity (per domain) | 4kb | 5MB | 5MB |
| Access | Across windows/tabs | Across windows/tabs | Same tab |
| Security | JavaScript cannot access `HttpOnly` cookies | None | None |
---
## Storage on the web
Cookies, `localStorage`, and `sessionStorage`, are all storage mechanisms on the client (web browser). It is useful to store data on the client for client-only state like access tokens, themes, personalized layouts, so that users can have a consistent experience on a website across tabs and usage sessions.
These client-side storage mechanisms have the following common properties:
- This means the clients can read and modify the values (except for `HttpOnly` cookies).
- Key-value based storage.
- They are only able to store values as strings. Non-strings will have to be serialized into a string (e.g. `JSON.stringify()`) in order to be stored.
### Use cases for each storage mechanism
Since cookies have a relatively low maximum size, it is not advisable to store all your client-side data within cookies. The distinguishing properties about cookies are that cookies are sent to the server on every HTTP request so the low maximum size is a feature that prevents your HTTP requests from being too large due to cookies. Automatic expiry of cookies is a useful feature as well.
With that in mind, the best kind of data to store within cookies is small pieces of data that needs to be transmitted to the server, such as auth tokens, session IDs, analytics tracking IDs, GDPR cookie consent, language preferences that are important for authentication, authorization, and rendering on the server. These values are sometimes sensitive and can benefit from the `HttpOnly`, `Secure`, and `Expires`/`Max-Age` capabilities that cookies provide.
`localStorage` and `sessionStorage` both implement the [Web Storage API interface](https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API). Web Storages have a generous total capacity of 5MB, so storage size is usually not a concern. The key difference is that values stored in Web Storage are not automatically sent on HTTP requests. While you can manually include values from Web Storage when making AJAX/`fetch()` requests, the initial browser request will contain them.
Hence Web Storage should not be used to store data that is relied on by the server for the initial rendering of the page if server-side rendering is being used (typically authentication/authorization-related information). `localStorage` is most suitable for user preferences data that do not expire, like themes and layouts (if it is not important for the server to render the final layout). `sessionStorage` is most suitable for temporary data that only needs to be accessible within the current browsing session, such as form data (useful to preserve data during accidental reloads).
The following sections dive deeper into each client storage mechanism.
### Cookies
Cookies are used to store small pieces of data on the client side that can be sent back to the server with every HTTP request.
- **Storage capacity**: Limited to around 4KB for all cookies.
- **Lifespan**: Cookies can have a specific expiration date set using the `Expires` or `Max-Age` attributes. If no expiration date is set, the cookie is deleted when the browser is closed (session cookie).
- **Access**: Cookies are domain-specific and can be shared across different pages and subdomains within the same domain.
- **Security**: Cookies can be marked as `HttpOnly` to prevent access from JavaScript, reducing the risk of XSS attacks. They can also be secured with the `Secure` flag to ensure they are sent only when HTTPS is used.
```js
// Set a cookie for the name/key `auth_token` with an expiry.
document.cookie =
'auth_token=abc123def; expires=Fri, 31 Dec 2024 23:59:59 GMT; path=/';
// Read all cookies. There's no way to read specific cookies using `document.cookie`.
// You have to parse the string yourself.
console.log(document.cookie); // auth_token=abc123def
// Delete the cookie with the name/key `auth_token` by setting an
// expiry date in the past. The value doesn't matter.
document.cookie = 'auth_token=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/';
```
It is a pain to read/write to cookies. `document.cookie` returns a single string containing all the key/value pairs delimited by `;` and you have to parse the string yourself. The [`js-cookie`](https://github.com/js-cookie/js-cookie) npm library provides a simple and lightweight API for reading/writing cookies in JavaScript.
A modern native way of accessing cookies is via the the [Cookie Store API](https://developer.mozilla.org/en-US/docs/Web/API/Cookie_Store_API) which is only available on HTTPS pages.
```js
// Set a cookie. More options are available too.
cookieStore.set('auth_token', 'abc123def');
// Async method to access a single cookie and do something with it.
cookieStore.get('auth_token').then(...);
// Async method to get all cookies.
cookieStore.getAll().then(...);
// Async method to delete a single cookie.
cookieStore.delete('auth_token').then(() =>
console.log('Cookie deleted')
);
```
The CookieStore API is relatively new and may not be supported in all browsers (supported in latest Chrome and Edge as of June 2024). Refer to [caniuse.com](https://caniuse.com/mdn-api_cookiestore) for the latest compatibility.
### `localStorage`
`localStorage` is used for storing data that persists even after the browser is closed and reopened. It is designed for long-term storage of data.
- **Storage capacity**: Typically around 5MB per origin (varies by browser).
- **Lifespan**: Data in `localStorage` persists until explicitly deleted by the user or the application.
- **Access**: Data is accessible within all tabs and windows of the same origin.
- **Security**: All JavaScript on the page have access to values within `localStorage`.
```js
// Set a value in localStorage.
localStorage.setItem('key', 'value');
// Get a value from localStorage.
console.log(localStorage.getItem('key'));
// Remove a value from localStorage.
localStorage.removeItem('key');
// Clear all data in localStorage.
localStorage.clear();
```
### `sessionStorage`
`sessionStorage` is used to store data for the duration of the page session. It is designed for temporary storage of data.
- **Storage Capacity**: Typically around 5MB per origin (varies by browser).
- **Lifespan**: Data in `sessionStorage` is cleared when the page session ends (i.e., when the browser or tab is closed). Reloading the page does not destroy data within `sessionStorage`.
- **Access**: Data is only accessible within the current tab or window. Different tabs or windows with the same page will have different `sessionStorage` objects.
- **Security**: All JavaScript on the same page have access to values within `sessionStorage` for that page.
```js
// Set a value in sessionStorage.
sessionStorage.setItem('key', 'value');
// Get a value from sessionStorage.
console.log(sessionStorage.getItem('key'));
// Remove a value from sessionStorage.
sessionStorage.removeItem('key');
// Clear all data in sessionStorage.
sessionStorage.clear();
```
## Notes
There are also other client-side storage mechanisms like [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) which is more powerful than the above-mentioned technologies but more complicated to use.
## References
- [What is the difference between localStorage, sessionStorage, session and cookies?](https://stackoverflow.com/questions/19867599/what-is-the-difference-between-localstorage-sessionstorage-session-and-cookies)

View File

@ -1,13 +0,0 @@
{
"slug": "describe-the-difference-between-a-cookie-sessionstorage-and-localstorage",
"languages": [],
"companies": ["amazon", "bytedance"],
"premium": false,
"duration": 5,
"published": true,
"topics": ["html", "javascript"],
"importance": "high",
"difficulty": "medium",
"featured": true,
"ranking": 2
}

View File

@ -1,30 +0,0 @@
---
title: Descreva a diferença entre cookie, `sessionStorage` e `localStorage`.
---
Local storage is useful for storing data that the user will need to access later, such as offline data, because it stores the data in the browser and the system. This data will persist even if the user closes and reopens the browser and is accessible by other sites.
Session storage is a great way to improve the performance of your web applications. It stores data locally on the browser but is specific to (and only accessible by) the respective site/browser tab and is only available while the user is on the site/tab. This is a more secure storage method due to the restrictive access and promotes better site performance due to reduced data transfer between server and client.
Cookies are a good choice for storing data that should not be persisted for a long time, such as session IDs. Cookies allow you to set an expiry time at which point it would be deleted. Cookies can only be smaller sized data compared to the other two storage methods.
## Similaridades
Cookies, `localStorage`, and `sessionStorage`, são todos:
- Mecanismos de armazenamento no lado do cliente. Isso significa que os clientes podem ler e modificar os valores.
- Armazenamento baseado em chave-valor.
- Eles só são capazes de armazenar valores como strings. Objetos terão que ser serializados em uma string (`JSON.stringify()`) a fim de serem armazenados.
## Diferenças
| Propriedade | Cookie | `localStorage` | `sessionStorage` |
| --- | --- | --- | --- |
| Iniciador | Cliente ou servidor. O servidor pode usar o cabeçalho `Set-Cookie` | Cliente | Cliente |
| Vencimento | Definir manualmente | Para sempre | Ao fechar a aba |
| Persistente através de sessões do navegador | Depende se a expiração está definida | Sim | Não |
| Enviado para o servidor com cada solicitação HTTP | Os cookies são automaticamente enviados via cabeçalho `Cookie` | Não | Não |
| Capacidade (por domínio) | 4kb | 5MB | 5MB |
| Acesso | Quqlquer Janela | Quqlquer Janela | Mesma Guia |
Também existem outros mecanismos de armazenamento do lado do cliente, como [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) que é mais poderoso do que as tecnologias acima mencionadas, mas mais complicado de usar.

View File

@ -1,30 +0,0 @@
---
title: 描述cookie、 `sessionStorage` 和 `localStorage` 之间的差异。
---
LocalStorage 对于存储用户以后需要访问的数据很有用,例如离线数据,因为它把数据存储在浏览器和系统中。 即使用户关闭和重新打开浏览器,这些数据也将持续存在,并可被其他网站访问。
SessionStorage 是提高你的 Web 应用程序性能的一个好方法。 它在浏览器上本地存储数据,但特定于(并且只能由)各自的网站/浏览器标签访问,并且只有当用户在网站/标签上时才能使用。 由于限制性的访问,这是一个更安全的存储方法,并且由于减少了服务器和客户端之间的数据传输,促进了更好的网站性能。
对于存储不应长期保存的数据,如会话 IDCookies 是一个不错的选择。 Cookies 允许你设置一个过期时间,届时它将被删除。 与其他两种存储方法相比Cookies 只能是较小尺寸的数据。
## 相似性
Cookies、`localStorage`和`sessionStorage`都是:
- 客户端的存储机制。 这意味着客户端可以阅读和修改这些值。
- 基于键值的存储。
- 他们只能存储作为字符串的值。 对象必须序列化为字符串 (`JSON.stringify()`) 才能存储。
## 差异
| 属性 | Cookie | `localStorage` | `sessionStorage` |
| --- | --- | --- | --- |
| 发起方 | 客户端或服务器。 服务器可以使用 `Set-Cookie` 头 | 客户端 | 客户端 |
| 有效期 | 手动设置 | 永久 | 标签关闭时 |
| 跨浏览器会话的持久性 | 取决于是否设置过期时间 | 是 | 否 |
| 每次 HTTP 请求都发送到服务器 | Cookie 会自动通过 `Cookie` 头发送 | 否 | 否 |
| 容量(每个域) | 4kb | 5MB | 5MB |
| 访问权限 | 任何窗口 | 任何窗口 | 部分标签页 |
还有其他客户端存储机制,如 [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/ADI/IndexedDB_API),比上述技术更强大,但使用起来更复杂。

View File

@ -1,121 +0,0 @@
---
title: Describe the difference between `<script>`, `<script async>` and `<script defer>`
---
## TL;DR
All of these ways (`<script>`, `<script async>`, and `<script defer>`) are used to load and execute JavaScript files in an HTML document, but they differ in how the browser handles loading and execution of the script:
- `<script>` is the default way of including JavaScript. The browser blocks HTML parsing while the script is being downloaded and executed. The browser will not continue rendering the page until the script has finished executing.
- `<script async>` downloads the script asynchronously, in parallel with parsing the HTML. Executes the script as soon as it is available, potentially interrupting the HTML parsing. `<script async>` do not wait for each other and execute in no particular order.
- `<script defer>` downloads the script asynchronously, in parallel with parsing the HTML. However, the execution of the script is deferred until HTML parsing is complete, in the order they appear in the HTML.
Here's a table summarizing the 3 ways of loading `<script>`s in a HTML document.
| Feature | `<script>` | `<script async>` | `<script defer>` |
| --- | --- | --- | --- |
| Parsing behavior | Blocks HTML parsing | Runs parallel to parsing | Runs parallel to parsing |
| Execution order | In order of appearance | Not guaranteed | In order of appearance |
| DOM dependency | No | No | Yes (waits for DOM) |
---
## What `<script>` tags are for
`<script>` tags are used to include JavaScript on a web page. The `async` and `defer` attributes are used to change how/when the loading and execution of the script happens.
## `<script>`
For normal `<script>` tags without any `async` or `defer`, when they are encountered, HTML parsing is blocked, the script is fetched and executed immediately. HTML parsing resumes after the script is executed. This can block rendering of the page if the script is large.
Use `<script>` for critical scripts that the page relies on to render properly.
```html
<!DOCTYPE html>
<html>
<head>
<title>Regular Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Regular Script Example</h1>
<p>This content will be rendered before the script executes.</p>
<!-- Regular script -->
<script src="regular.js"></script>
<!-- Content after the script -->
<p>This content will be rendered after the script executes.</p>
</body>
</html>
```
{/* TODO: Add CSB examples for blocking scripts */}
## `<script async>`
In `<script async>`, the browser downloads the script file asynchronously (in parallel with HTML parsing) and executes it as soon as it is available (potentially before HTML parsing completes). The execution will not necessarily be executed in the order in which it appears in the HTML document. This can improve perceived performance because the browser doesn't wait for the script to download before continuing to render the page.
Use `<script async>` when the script is independent of any other scripts on the page, for example, analytics and ads scripts.
```html
<!DOCTYPE html>
<html>
<head>
<title>Async Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Async Script Example</h1>
<p>This content will be rendered before the async script executes.</p>
<!-- Async script -->
<script async src="async.js"></script>
<!-- Content after the script -->
<p>
This content may be rendered before or after the async script executes.
</p>
</body>
</html>
```
## `<script defer>`
Similar to `<script async>`, `<script defer>` also downloads the script in parallel to HTML parsing but the script is only executed when the document has been fully parsed and before firing `DOMContentLoaded`. If there are multiple of them, each deferred script is executed in the order they appeared in the HTML document.
If a script relies on a fully-parsed DOM, the `defer` attribute will be useful in ensuring that the HTML is fully parsed before executing.
```html
<!DOCTYPE html>
<html>
<head>
<title>Deferred Script</title>
</head>
<body>
<!-- Content before the script -->
<h1>Deferred Script Example</h1>
<p>This content will be rendered before the deferred script executes.</p>
<!-- Deferred script -->
<script defer src="deferred.js"></script>
<!-- Content after the script -->
<p>This content will be rendered before the deferred script executes.</p>
</body>
</html>
```
## Notes
- The `async` attribute should be used for scripts that are not critical to the initial rendering of the page and do not depend on each other, while the `defer` attribute should be used for scripts that depend on / is depended on by another script.
- The `async` and `defer` attributes are ignored for scripts that have no `src` attribute.
- `<script>`s with `defer` or `async` that contain `document.write()` will be ignored with a message like "A call to `document.write()` from an asynchronously-loaded external script was ignored".
- Even though `async` and `defer` help to make script downloading asynchronous, the scripts are still eventually executed on the main thread. If these scripts are computationally intensive, it can result in laggy/frozen UI. [Partydown](https://partytown.builder.io/) is a library that helps relocate script executions into a [web worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) and off the [main thread](https://developer.mozilla.org/en-US/docs/Glossary/Main_thread), which is great for third-party scripts where you do not have control over the code.
{/* TODO: Add image https://media.licdn.com/dms/image/D5612AQEYCnsZ1f9GFQ/article-cover_image-shrink_600_2000/0/1699370054733?e=2147483647&v=beta&t=MeKuUXk5QMblVoausf5p3swTkBCICOHoRsijQqMfxZE */}
## Further reading
- [`<script>`: The Script element | MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#defer)
- [async vs defer attributes](https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)

View File

@ -1,13 +0,0 @@
{
"slug": "describe-the-difference-between-script-async-and-script-defer",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["html", "javascript"],
"importance": "high",
"difficulty": "medium",
"featured": false,
"ranking": 1
}

View File

@ -1,30 +0,0 @@
---
title: Descreva a diferença entre `<script>`, `<script async>` e `<script defer>`
---
tags `<script>` são usadas para incluir JavaScript em uma página da web. Os atributos `async` e `defer` são usados para mudar como/quando o carregamento e a execução do script acontecem.
## Simples `<script>`
Para tags normais `<script>` sem qualquer `async` ou `defer`, quando forem encontrados, a análise do HTML é bloqueada, o script é buscado e executado imediatamente. A análise do HTML é retomada após a execução do script.
## `<script async>`
No `<script async>`, o script será buscado em paralelo à análise do HTML e será executado assim que estiver disponível (potencialmente antes da conclusão da análise do HTML) e não será necessariamente executado na ordem em que aparece no documento HTML. Use `async` quando o script é independente de quaisquer outros scripts na página, por exemplo, analytics.
## `<script defer>`
No `<script defer>`, o script será buscado em paralelo à análise HTML e executado quando o documento tiver sido totalmente analisado, mas antes de disparar `DOMContentLoaded`. Se houver múltiplos, cada script adiado é executado na ordem em que eles apareceram no documento HTML.
Se um script depende de um DOM totalmente analisado, o atributo `defer` será útil para garantir que o HTML seja totalmente analisado antes de ser executado.
## Notas
- Geralmente, o atributo `async` deve ser usado para scripts que não são críticos para a renderização inicial da página e não dependem um do outro. enquanto o atributo `defer` deve ser usado para scripts que dependem de / é dependente de outro script.
- Os atributos `async` e `defer` são ignorados para scripts que não têm o atributo `src`.
- `<script>`s com `defer` ou `async` que contêm `document.write()` serão ignorados com uma mensagem como "Uma chamada para o documento.write() de um script externo carregado de forma assíncrona foi ignorada".
## Referências
- [`<script>`: O elemento Script | MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#defer)
- [async vs defer attributes](https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)

View File

@ -1,30 +0,0 @@
---
title: 描述`<script>`、`<script async>`和`<script defer> `之间的差异
---
`<script>` 标签用于在网页上包含 JavaScript 。 `async` 和 `defer` 属性用于更改脚本加载和执行的方式/时机。
## 普通`<script>`
对于普通的 `<script>` 标签,在遇到它们时没有任何`async` 或 `defer`。 HTML 解析被阻止,脚本会被下载并立即执行。 脚本执行后 HTML 解析恢复。
## `<script async>`
在`<script async>`中,脚本将与 HTML 解析并行获取,并在其可用时立即执行(可能在 HTML 解析完成之前),而且不一定按照 HTML 文档中的顺序执行。 当脚本独立于页面上的任何其他脚本时使用 `async` ,比如分析。
## `<script defer>`
在`<script defer>`, 脚本将在文档已完全解析并执行时并行获取到 HTML 解析和执行, 但在 `DOMContentLoaded` 事件之前。 如果其中有多个,每个 defer 脚本都是按照它们在 HTML 文档中出现的顺序执行的。
如果脚本依赖于完全解析的 DOM则`defer` 属性将有助于确保在执行前完全解析 HTML。
## 备注
- 一般说来, `async` 属性应该用于对页面初始化不重要且不依赖于对方的脚本。 `defer` 属性应该用于依赖于/被依赖于其他脚本的脚本。
- 没有`src`属性的脚本, `async` 和 `deleger` 属性会被忽略。
- 包含`defer'或`async'的`<script>`将被忽略,并显示 "来自异步加载的外部脚本对 document.write()的调用被忽略 "的信息。
## 参考资料
- [`<script>`: 脚本元素 | MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#defer)
- [async vs defer 属性](https://www.growingwiththeweb.com/2014/02/async-vs-defer-attributes.html)

View File

@ -1,7 +0,0 @@
---
title: Difference between document `load` event and document `DOMContentLoaded` event?
---
The `DOMContentLoaded` event is fired when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
`window`'s `load` event is only fired after the DOM and all dependent resources and assets have loaded.

View File

@ -1,11 +0,0 @@
{
"slug": "difference-between-document-load-event-and-document-domcontentloaded-event",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "medium"
}

View File

@ -1,7 +0,0 @@
---
title: Qual a diferença entre o evento `load` do documento e o evento `DOMContentLoaded` do documento?
---
O evento `DOMContentLoaded` é disparado quando o documento HTML inicial foi completamente carregado e analisado, sem esperar que folhas de estilo, imagens e subframes terminem de carregar.
O evento `load` do `window` só é disparado após o DOM e todos os recursos e ativos dependentes terem sido carregados.

View File

@ -1,7 +0,0 @@
---
title: Document `load` 事件和 `DOMContentLoaded` 事件之间的区别?
---
当初始的 HTML 文档被完全加载并解析时,`DOMContentLoaded` 事件将被触发。 无需等待样式表、图片和子帧来完成加载。
`window` 上的 `load` 事件只在 DOM 和所有依赖的资源和资产加载后才能触发。

View File

@ -1,79 +0,0 @@
---
title: 'Difference between: `function Person(){}`, `const person = Person()`, and `const person = new Person()`?'
---
## TL;DR
- `function Person(){}`: A function declaration in JavaScript. It can be used as a regular function or as a constructor.
- `const person = Person()`: Calls `Person` as a regular function, not a constructor. If `Person` is intended to be a constructor, this will lead to unexpected behavior.
- `const person = new Person()`: Creates a new instance of `Person`, correctly utilizing the constructor function to initialize the new object.
| Aspect | `function Person(){}` | `const person = Person()` | `const person = new Person()` |
| --- | --- | --- | --- |
| Type | Function declaration | Function call | Constructor call |
| Usage | Defines a function | Invokes `Person` as a regular function | Creates a new instance of `Person` |
| Instance Creation | No instance created | No instance created | New instance created |
| Common Mistake | N/A | Misusing as constructor leading to `undefined` | None (when used correctly) |
---
## Function declaration
`function Person(){}` is a standard function declaration in JavaScript. When written in PascalCase, it follows the convention for functions intended to be used as constructors.
```js
function Person(name) {
this.name = name;
}
```
This code defines a function named `Person` that takes a parameter `name` and assigns it to the `name` property of the object created from this constructor function. When the `this` keyword is used in a constructor, it refers to the newly created object.
## Function call
`const person = Person()` simply invoke the function's code. When you invoke `Person` as a regular function (i.e., without the `new` keyword), the function does not behave as a constructor. Instead, it executes its code and returns `undefined` if no return value is specified and that gets assigned to the variable intended as the instance. Invoking as such is a common mistake if the function is intended to be used as a constructor.
```js
function Person(name) {
this.name = name;
}
const person = Person('John');
console.log(person); // undefined
console.log(person.name); // Uncaught TypeError: Cannot read property 'name' of undefined
```
In this case, `Person('John')` does not create a new object. The `person` variable is assigned `undefined` because the `Person` function does not explicitly return a value. Attempting to access `person.name` throws an error because `person` is `undefined`.
## Constructor call
`const person = new Person()` creates an instance of the `Person` object using the new operator, which inherits from `Person.prototype`. An alternative would be to use `Object.create`, such as: `Object.create(Person.prototype)` and `Person.call(person, 'John')` initializes the object.
```js
function Person(name) {
this.name = name;
}
const person = new Person('John');
console.log(person); // Person { name: 'John' }
console.log(person.name); // 'John'
// Alternative
const person1 = Object.create(Person.prototype);
Person.call(person1, 'John');
console.log(person1); // Person { name: 'John' }
console.log(person1.name); // 'John'
```
In this case, `new Person('John')` creates a new object, and `this` within `Person` refers to this new object. The `name` property is correctly set on the new object. The `person` variable is assigned the new instance of `Person` with the name property set to `'John'`. And for the alternative object creation, `Object.create(Person.prototype)` creates a new object with `Person.prototype` as its prototype. `Person.call(person, 'John')` initializes the object, setting the `name` property.
## Follow-Up Questions
- What are the differences between function constructors and ES6 class syntax?
- What are some common use cases for `Object.create`?
## Further reading
- [MDN Web Docs: Object prototypes](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Objects/Object_prototypes)
- [Differences between Class and Function Constructors](https://www.greatfrontend.com/questions/quiz/what-are-the-differences-between-es6-class-and-es5-function-constructors?fpr=yangshun)
- [How `this` keyword works in JavaScript?](https://www.greatfrontend.com/questions/quiz/explain-how-this-works-in-javascript?fpr=yangshun)

View File

@ -1,11 +0,0 @@
{
"slug": "difference-between-function-person-var-person-person-and-var-person-new-person",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "mid",
"difficulty": "medium"
}

View File

@ -1,23 +0,0 @@
---
title: 'Diferença entre: `function Person(){}`, `var person = Person()`, e `var person = new Person()`?'
---
Esta pergunta é muito vaga. Nossa melhor suposição sobre a intenção dessa pergunta é que ela está perguntando sobre construtores em JavaScript. Tecnicamente falando, `function Person(){}` é apenas uma declaração de função normal. A convenção é usar PascalCase para funções que se destinam a ser usadas como construtores.
`var person = Person()` invoca o `Person` como uma função, e não como um construtor. Invocar como tal é um erro comum se a função pretende ser usada como um construtor. Normalmente, o construtor não devolve nada. Assim, invocando o construtor como uma função normal retornará `undefined` e que será atribuído à variável pretendida como a instância.
`var person = new Person()` cria uma instância do objeto `Person` usando o operador `new`, que herda de `Person.prototype`. Uma alternativa seria usar `Object.create`, tais como: `Object.create(Person.prototype)`.
```js
function Person(name) {
this.name = name;
}
var person = Person('John');
console.log(person); // undefined
console.log(person.name); // Uncaught TypeError: Cannot read property 'name' of undefined
var person = new Person('John');
console.log(person); // Person { name: "John" }
console.log(person.name); // "john"
```

View File

@ -1,23 +0,0 @@
---
title: '比较差异: `function Person(){}`, `var person = Person()`, 和 `var person = new Person()`?'
---
这个问题相当含糊。 我们对其意图的最好猜测是,它在询问 JavaScript 中的构造函数。 从技术上讲,`function Person(){}` 只是一个正常函数声明。 惯例是对打算作为构造函数使用的函数使用 PascalCase。
`var persons = Person()` 将`Person` 作为函数,而不是作为构造函数。 如果要将函数用作构造函数,这样的动作是常见的错误。 构造函数通常不会返回任何东西。 因此,调用构造函数像一个正常函数会返回 `undefined` ,它会被分配给指定为实例的变量。
`var persone = new Person()` 创建一个 `Person` 对象的实例,使用`new` 操作符继承了 `Person.prototype`。 另一种办法是使用 `Object.create`,例如:`Object.create(Person.prototype)`。
```js
function Person(name) {
this.name = name;
}
var person = Person('John');
console.log(person); // undefined
console.log(person.name); // Uncaught TypeError: Cannot read property 'name' of undefined
var person = new Person('John');
console.log(person); // Person { name: "John" }
console.log(person.name); // "john"
```

View File

@ -1,62 +0,0 @@
---
title: ES2015 Template Literals offer a lot of flexibility in generating strings, can you give an example?
---
Template literals help make it simple to do string interpolation, or to include variables in a string. Before ES2015, it was common to do something like this:
```js
var person = { name: 'Tyler', age: 28 };
console.log(
'Hi, my name is ' + person.name + ' and I am ' + person.age + ' years old!',
);
// 'Hi, my name is Tyler and I am 28 years old!'
```
With template literals, you can now create that same output like this instead:
```js
const person = { name: 'Tyler', age: 28 };
console.log(`Hi, my name is ${person.name} and I am ${person.age} years old!`);
// 'Hi, my name is Tyler and I am 28 years old!'
```
Note that you use backticks, not quotes, to indicate that you are using a template literal and that you can insert expressions inside the `${}` placeholders.
A second helpful use case is in creating multi-line strings. Before ES2015, you could create a multi-line string like this:
```js
console.log('This is line one.\nThis is line two.');
// This is line one.
// This is line two.
```
Or if you wanted to break it up into multiple lines in your code so you didn't have to scroll to the right in your text editor to read a long string, you could also write it like this:
```js
console.log('This is line one.\n' + 'This is line two.');
// This is line one.
// This is line two.
```
Template literals, however, preserve whatever spacing you add to them. For example, to create that same multi-line output that we created above, you can simply do:
```js
console.log(`This is line one.
This is line two.`);
// This is line one.
// This is line two.
```
Another use case of template literals would be to use as a substitute for templating libraries for simple variable interpolations:
```js
const person = { name: 'Tyler', age: 28 };
document.body.innerHTML = `
<div>
<p>Name: ${person.name}</p>
<p>Age: ${person.age}</p>
</div>
`;
```
**Note that your code may be susceptible to XSS by using `.innerHTML`. Sanitize your data before displaying it if it came from a user!**

View File

@ -1,11 +0,0 @@
{
"slug": "es6-template-literals-offer-a-lot-of-flexibility-in-generating-strings-can-you-give-an-example",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "easy"
}

View File

@ -1,66 +0,0 @@
---
title: Template Literals do ES2015 oferecem muita flexibilidade na geração de strings, você pode dar um exemplo?
---
Os literais de template ajudam a simplificar a interpolação de strings ou a incluir variáveis em uma string. Antes do ES2015, era comum fazer algo assim:
```js
var person = { name: 'Tyler', age: 28 };
console.log(
'Oi, meu nome é ' +
person.name +
' e eu sou ' +
pessoa.age +
' anos de idade!',
);
// 'Oi, meu nome é Tyler e eu tenho 28 anos!'
```
Com os template literals, agora você pode criar a mesma saída assim:
```js
const person = { name: 'Tyler', age: 28 };
console.log(`Oi, meu nome é ${person.name} e tenho ${person.age} anos!`);
// 'Oi, meu nome é Tyler e eu tenho 28 anos!'
```
Observe que você usa backticks, não aspas, para indicar que você está usando um texto literal e que você pode inserir expressões dentro dos espaços reservados `${}`.
Um segundo caso útil de uso é a criação de strings de várias linhas. Antes de ES2015, você pode criar uma string multi-linha como esta:
```js
console.log('Esta é a linha um.\nEsta é a linha dois.');
// Esta é a linha um.
// Esta é a linha dois.
```
Ou se você quisesse dividi-lo em várias linhas no seu código, para que você não tenha que rolar até a direita no seu editor de texto para ler uma longa string, você também poderia escrever assim:
```js
console.log('Esta é a linha um.\n' + 'Esta é a linha dois.');
// Esta é a linha um.
// Esta é a linha dois.
```
Os template literals, no entanto, preservam qualquer espaçamento que você adicionar a eles. Por exemplo, para criar a mesma saída multi-linha que criamos acima, você pode simplesmente fazer:
```js
console.log(`Esta é a linha um.
Esta é a linha dois.`);
// Esta é a linha um.
// Esta é a linha dois.
```
Um outro caso de uso de template literals seria usar como substituto para as bibliotecas de templates para interpolações variáveis simples:
```js
const person = { name: 'Tyler', age: 28 };
document.body.innerHTML = `
<div>
<p>Nome: ${person.name}</p>
<p>Idade: ${person.age}</p>
</div>
`;
```
**Note que seu código pode ser suscetível a XSS usando `.innerHTML`. Higienize seus dados antes de exibi-los se vierem de um usuário!**

View File

@ -1,62 +0,0 @@
---
title: ES2015 模板字面量在生成字符串时具有很大的灵活性,您能给出一个例子吗?
---
模板字面量有助于简单地进行字符串插值,或在字符串中包含变量。 在 ES2015 之前,常见的做法是做这样的:
```js
var person = { name: 'Tyler', age: 28 };
console.log(
'Hi, my name is ' + person.name + ' and I am ' + person.age + ' years old!',
);
// 'Hi, my name is Tyler and I am 28 years old!'
```
使用模板字面量,您现在可以创建相同的结果像这样:
```js
const person = { name: 'Tyler', age: 28 };
console.log(`Hi, my name is ${person.name} and I am ${person.age} years old!`);
// 'Hi, my name is Tyler and I am 28 years old!'
```
请注意您使用反引号而不是引号, 指示您使用的是一个字段,您可以在 `${}` 占位符中插入表达式。
第二个有用的案例是创建多行字符串。 在 ES2015 之前,您可以创建一个多行字符串像这样:
```js
console.log('This is line one.\nThis is line two.');
// This is line one.
// This is line two.
```
或者如果你想要将它分成你的代码中的多行,所以你不必滚动到你的文本编辑器中的右边阅读一个长字符串, 你也可以像这样写:
```js
console.log('This is line one.\n' + 'This is line two.');
// This is line one.
// This is line two.
```
然而,模板字面量保留您添加到它们的任何空格、换行。 例如,要创建与我们在上面创建的相同的多行输出, 你可以简单地做:
```js
console.log(`This is line one.
This is line two.`);
// This is line one.
// This is line two.
```
模板字面量的另一个使用情况是作为简单变量插值的模板库的替代物:
```js
const person = { name: 'Tyler', age: 28 };
document.body.innerHTML = `
<div>
<p>Name: ${person.name}</p>
<p>Age: ${person.age}</p>
</div>
`;
```
**注意你的代码可能会因为使用`.innerHTML`而受到 XSS 的影响。 如果数据来自一个用户,请在显示数据之前将其净化!**

View File

@ -1,124 +0,0 @@
---
title: Explain AJAX in as much detail as possible
---
## TL;DR
AJAX (Asynchronous JavaScript and XML) facilitates asynchronous communication between the client and server, enabling dynamic updates to web pages without reloading. It uses techniques like `XMLHttpRequest` or the `fetch()` API to send and receive data in the background. In modern web applications, the `fetch()` API is more commonly used to implement AJAX.
**Using `XMLHttpRequest`**
```js
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error('Request failed: ' + xhr.status);
}
}
};
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true);
xhr.send();
```
**Using `fetch()`**
```js
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error('Fetch error:', error));
```
---
## AJAX (Asynchronous JavaScript and XML)
AJAX (asynchronous JavaScript and XML) is a set of web development techniques using many web technologies on the client side to create asynchronous web applications. Unlike traditional web applications where every user interaction triggers a full page reload, with AJAX, web applications can send data to and retrieve from a server asynchronously (in the background) without interfering with the display and behavior of the existing page. By decoupling the data interchange layer from the presentation layer, AJAX allows for web pages, and by extension web applications, to change content dynamically without the need to reload the entire page. In practice, modern implementations commonly use JSON instead of XML, due to the advantages of JSON being native to JavaScript.
Traditionally, AJAX was implemented using the `XMLHttpRequest` API, but the `fetch()` API is more suitable and easier to use for modern web applications.
## `XMLHttpRequest` API
Here's a basic example of how it can be used:
```js
let xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
console.error('Request failed: ' + xhr.status);
}
}
};
xhr.open('GET', 'https://jsonplaceholder.typicode.com/todos/1', true);
xhr.send();
```
## `fetch()` API
Alternatively, the `fetch()` API provides a modern, promise-based approach to making AJAX requests. It is more commonly used in modern web applications.
Here's how you can use it:
```js
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then((response) => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.then((data) => console.log(data))
.catch((error) => console.error('Fetch error:', error));
```
## How does AJAX work?
In modern browsers, AJAX is done using the `fetch()` API instead of `XMLHTTPRequest`, so we will explain how the `fetch()` API works instead:
1. **Making a request**: The [`fetch()` function](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) initiates an asynchronous request to fetch a resource from a URL. It takes one mandatory argument the URL of the resource to fetch, and optionally accepts a second argument - an `options` object that allows configuring the HTTP request with options like the HTTP method, headers, body, etc.
```js
fetch('https://api.example.com/data', {
method: 'GET', // or 'POST', 'PUT', 'DELETE', etc.
headers: {
'Content-Type': 'application/json',
},
});
```
2. **Return a promise**: The `fetch()` function returns a `Promise` that resolves to a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) object representing the response from the server. This `Promise needs` to be handled using `.then()` or `async/await`.
3. **Handling the response**: The `Response` object provides methods to define how the body content should be handled, such as `.json()` for parsing JSON data, `.text()` for plain text, `.blob()` for binary data, etc.
```js
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => console.log(data))
.catch((error) => console.error('Error:', error));
```
4. **Asynchronous nature** The `fetch` API is asynchronous, allowing the browser to continue executing other tasks while waiting for the server response. This prevents blocking the main thread and provides a better user experience. The `then()` and `catch()` callbacks are put onto the microtask queue when executed as part of the [event loop](/questions/quiz/what-is-event-loop-what-is-the-difference-between-call-stack-and-task-queue).
5. **Request options** The optional second argument to `fetch()` allows configuring various aspects of the request, such as the HTTP method, headers, body, credentials, caching behavior, and more.
6. **Error handling** Errors during the request, such as network failures or invalid responses, are caught and propagated through the Promise chain using the `.catch()` method or try/catch blocks with `async/await`.
The `fetch()` API provides a modern, Promise-based approach to making HTTP requests in JavaScript, replacing the older `XMLHttpRequest` API. It offers a simpler and more flexible way to interact with APIs and fetch resources from servers, while integrating advanced HTTP concepts like CORS and other extensions.
## Advantages and disadvantages of AJAX
While useful, using AJAX also comes with some considerations. Read more about the [advantages and disadvantages of AJAX](/questions/quiz/what-are-the-advantages-and-disadvantages-of-using-ajax).
## Further reading
- [AJAX | MDN](https://developer.mozilla.org/en-US/docs/Glossary/AJAX)
- [Fetch API | MDN ](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)
- [XMLHttpRequest | MDN](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-ajax-in-as-much-detail-as-possible",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "network"],
"importance": "mid",
"difficulty": "hard"
}

View File

@ -1,7 +0,0 @@
---
title: Explique o Ajax com o máximo de detalhes possível.
---
Ajax (asynchronous JavaScript and XML) é um conjunto de técnicas de desenvolvimento web que utilizam diversas tecnologias web no lado do cliente para criar aplicações web assíncronas. Com o Ajax, as aplicações web podem enviar dados para e receber do servidor de forma assíncrona (em segundo plano) sem interferir na exibição e comportamento da página existente. Ao separar a camada de intercâmbio de dados da camada de apresentação, o Ajax permite que páginas web, e por extensão, aplicações web, alterem o conteúdo dinamicamente sem precisar recarregar toda a página. Na prática, implementações modernas comumente usam JSON em vez de XML, devido às vantagens de o JSON ser nativo ao JavaScript.
A API `XMLHttpRequest` é frequentemente usada para a comunicação assíncrona ou hoje em dia, a API fetch.

View File

@ -1,7 +0,0 @@
---
title: 尽可能详细地解释Ajax
---
Ajax (异步 JavaScript 和 XML) 是一套网络开发技术,在客户端使用许多网络技术创建异步 Web 应用程序。 使用 Ajax Web 应用程序可以将数据异步地发送到服务器(后端)并从服务器上检索,而不干扰现有页面的显示和行为。 通过将数据交换层与表现层解耦Ajax 允许网页,以及扩展的 Web 应用程序,动态地改变内容,而不需要重新加载整个页面。 实际上,现代实现通常使用 JSON 而不是 XML因为 JSON 是 JavaScript 的原生优势。
`XMLHttpRequest` API 或如今的 `fetch()` API 经常用于异步通信。

View File

@ -1,133 +0,0 @@
---
title: Explain event delegation
---
## TL;DR
Event delegation is a technique in JavaScript where a single event listener is attached to a parent element instead of attaching event listeners to multiple child elements. When an event occurs on a child element, the event bubbles up the DOM tree, and the parent element's event listener handles the event based on the target element.
Event delegation provides the following benefits:
- **Improved performance**: Attaching a single event listener is more efficient than attaching multiple event listeners to individual elements, especially for large or dynamic lists. This reduces memory usage and improves overall performance.
- **Simplified event handling**: With event delegation, you only need to write the event handling logic once in the parent element's event listener. This makes the code more maintainable and easier to update.
- **Dynamic element support**: Event delegation automatically handles events for dynamically added or removed elements within the parent element. There's no need to manually attach or remove event listeners when the DOM structure changes
However, do note that:
- It is important to identify the target element that triggered the event.
- Not all events can be delegated because they are not bubbled. Non-bubbling events include: `focus`, `blur`, `scroll`, `mouseenter`, `mouseleave`, `resize`, etc.
---
## Event delegation
Event delegation is a design pattern in JavaScript used to efficiently manage and handle events on multiple child elements by attaching a single event listener to a common ancestor element. This pattern is particularly valuable in scenarios where you have a large number of similar elements, such as list items, and want to optimize event handling.
## How event delegation works
1. **Attach a listener to a common ancestor**: Instead of attaching individual event listeners to each child element, you attach a single event listener to a common ancestor element higher in the DOM hierarchy.
1. **Event bubbling**: When an event occurs on a child element, it bubbles up through the DOM tree to the common ancestor element. During this propagation, the event listener on the common ancestor can intercept and handle the event.
1. **Determine the target**: Within the event listener, you can inspect the event object to identify the actual target of the event (the child element that triggered the event). You can use properties like `event.target` or `event.currentTarget` to determine which specific child element was interacted with.
1. **Perform action based on target**: Based on the target element, you can perform the desired action or execute code specific to that element. This allows you to handle events for multiple child elements with a single event listener.
## Benefits of event delegation
1. **Efficiency**: Event delegation reduces the number of event listeners, improving memory usage and performance, especially when dealing with a large number of elements.
1. **Dynamic elements**: It works seamlessly with dynamically added or removed child elements, as the common ancestor continues to listen for events on them.
## Example
Here's a simple example:
```js
// HTML:
// <ul id="item-list">
// <li>Item 1</li>
// <li>Item 2</li>
// <li>Item 3</li>
// </ul>
const itemList = document.getElementById('item-list');
itemList.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
console.log(`Clicked on ${event.target.textContent}`);
}
});
```
In this example, a single click event listener is attached to the `<ul>` element. When a click event occurs on an `<li>` element, the event bubbles up to the `<ul>` element, where the event listener checks the target's tag name to identify whether a list item was clicked. It's crucial to check the identity of the `event.target` as there can be other kinds of elements in the DOM tree.
## Use cases
Event delegation is commonly used in scenarios like:
### Handling dynamic content in single-page applications
```js
// HTML:
// <div id="button-container">
// <button>Button 1</button>
// <button>Button 2</button>
// </div>
// <button id="add-button">Add Button</button>
const buttonContainer = document.getElementById('button-container');
const addButton = document.getElementById('add-button');
buttonContainer.addEventListener('click', (event) => {
if (event.target.tagName === 'BUTTON') {
console.log(`Clicked on ${event.target.textContent}`);
}
});
addButton.addEventListener('click', () => {
const newButton = document.createElement('button');
newButton.textContent = `Button ${buttonContainer.children.length + 1}`;
buttonContainer.appendChild(newButton);
});
```
In this example, a `click` event listener is attached to the `<div>` container. When a new button is added dynamically and clicked, the event listener on the container handles the click event.
### Simplifying code by avoiding the need to attach and remove event listeners for elements that change
```js
// HTML:
// <form id="user-form">
// <input type="text" name="username" placeholder="Username">
// <input type="email" name="email" placeholder="Email">
// <input type="password" name="password" placeholder="Password">
// </form>
const userForm = document.getElementById('user-form');
userForm.addEventListener('input', (event) => {
const { name, value } = event.target;
console.log(`Changed ${name}: ${value}`);
});
```
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 `<input>` element.
## Pitfalls
Do note that event delegation come with certain pitfalls:
- **Incorrect target handling:** Ensure correct identification of the event target to avoid unintended actions.
- **Not all events can be delegated/bubbled**: Not all events can be delegated because they are not bubbled. Non-bubbling events include: `focus`, `blur`, `scroll`, `mouseenter`, `mouseleave`, `resize`, etc.
- **Event overhead:** While event delegation is generally more efficient, there needs to be complex logic written within the root event listener to identify the triggering element and respond appropriately. This can introduce overhead and can be potentially more complex if not managed properly.
## Event delegation in JavaScript frameworks
In [React](https://react.dev/), event handlers are attached to the React root's DOM container into which the React tree is rendered. Even though `onClick` is added to child elements, the actual event listeners are attached to the root DOM node, leveraging event delegation to optimize event handling and improve performance.
When an event occurs, React's event listener captures it and determines which React component rendered the target element based on its internal bookkeeping. React then dispatches the event to the appropriate component's event handler by calling the handler function with a synthetic event object. This synthetic event object wraps the native browser event, providing a consistent interface across different browsers and capturing information about the event.
By using event delegation, React avoids attaching individual event handlers to each component instance, which would create significant overhead, especially for large component trees. Instead, React leverages the browser's native event bubbling mechanism to capture events at the root and distribute them to the appropriate components.
## Further reading
- [MDN Web Docs on Event Delegation](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation)
- [JavaScript.info - Event Delegation](https://javascript.info/event-delegation)
- [React v17.0 Release Candidate: No New Features](https://legacy.reactjs.org/blog/2020/08/10/react-v17-rc.html#changes-to-event-delegation)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-event-delegation",
"languages": [],
"companies": ["linkedin"],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "html"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,47 +0,0 @@
---
title: Explique delegação do evento
---
A delegação de eventos é um conceito fundamental no desenvolvimento web que permite gerenciar e tratar eventos eficientemente em vários elementos filhos, anexando um único ouvinte de eventos a um elemento ancestral comum. Em vez de atribuir ouvintes de eventos a cada elemento filho individualmente, você delega a responsabilidade de lidar com eventos ao elemento pai ou ancestral, que intercepta os eventos à medida que eles sobem na árvore DOM e identifica o alvo do evento.
## Benefícios da delegação de eventos
1. **Eficiência**: A delegação de eventos reduz significativamente o número de ouvintes de eventos em seu código, tornando-o mais eficiente em termos de memória e melhorando o desempenho, especialmente ao lidar com um grande número de elementos semelhantes. Isso resulta em um código mais limpo e de fácil manutenção.
2. **Elementos Dinâmicos**: A delegação de eventos funciona perfeitamente com elementos gerados ou removidos dinamicamente no DOM. Você não precisa anexar ou remover ouvintes de eventos toda vez que novos elementos são adicionados ou removidos. O ouvinte de eventos delegado os trata automaticamente.
## Exemplo
Vamos ilustrar a delegação de eventos com um exemplo moderno usando a sintaxe do ES6:
```js
// HTML:
// <ul id="item-list">
// <li>Item 1</li>
// <li>Item 2</li>
// <li>Item 3</li>
// </ul>
const itemList = document.getElementById('item-list');
itemList.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
console.log(`Clicou em ${event.target.textContent}`);
}
});
```
Neste exemplo, um único ouvinte de eventos de clique é anexado ao elemento `<ul>`. Quando ocorre um evento de clique em um elemento `<li>`, o evento se propaga até o elemento `<ul>`, onde o ouvinte de eventos verifica o nome da tag do alvo para identificar qual item da lista foi clicado.
## Casos de uso
A delegação de eventos é comumente usada em várias situações, incluindo:
1. Gerenciamento de listas, menus ou tabelas com muitos itens ou linhas.
1. Manipulação de conteúdo dinâmico em aplicativos de página única.
1. Simplificação do código, evitando a necessidade de anexar e remover ouvintes de eventos para elementos que mudam.
## Recursos
- [MDN Web Docs sobre Delegação de Eventos](https://developer.mozilla.org/pt-BR/docs/Learn/JavaScript/Building_blocks/Events#event_delegation)
- [JavaScript.info - Delegação de Eventos](https://javascript.info/event-delegation)

View File

@ -1,53 +0,0 @@
---
title: 解释事件委托
---
事件委托是 JavaScript 中的一种设计模式,用于通过将单个事件监听器附加到共同的祖先元素,高效地管理和处理多个子元素上的事件。这个模式在你有大量类似元素(例如列表项)并希望简化事件处理的情况下尤为有价值。
## 事件委托的工作原理
1. **将监听器附加到共同的祖先元素**:与将单独的事件监听器附加到每个子元素不同,你将一个单一的事件监听器附加到 DOM 层次结构中较高的共同祖先元素上。
1. **事件冒泡**:当事件在子元素上发生时,它通过 DOM 树冒泡到共同祖先元素。在此传播期间,共同祖先上的事件监听器可以拦截并处理事件。
1. **确定目标**:在事件监听器内部,你可以检查事件对象以识别事件的实际目标(触发事件的子元素)。你可以使用`event.target`或`event.currentTarget`等属性来确定与哪个特定子元素进行了交互。
1. **根据目标执行操作**:根据目标元素,你可以执行所需的操作或执行特定于该元素的代码。这使你能够使用单个事件监听器处理多个子元素的事件。
## 事件委托的优点
1. **效率**:事件委托减少了事件监听器的数量,提高了内存使用和性能,特别是在处理大量元素时。
1. **动态元素**:它与动态添加或删除的子元素无缝配合,因为共同祖先继续监听它们的事件。
## 示例
以下是使用现代 ES6 语法的简单示例:
```js
// HTML:
// <ul id="item-list">
// <li>项目 1</li>
// <li>项目 2</li>
// <li>项目 3</li>
// </ul>
const itemList = document.getElementById('item-list');
itemList.addEventListener('click', (event) => {
if (event.target.tagName === 'LI') {
console.log(`单击了 ${event.target.textContent}`);
}
});
```
在此示例中,单个点击事件监听器附加到了`<ul>`元素上。当在`<li>`元素上发生点击事件时,事件冒泡到了`<ul>`元素,事件监听器检查目标的标签名称以识别单击的列表项。
## 用例
事件委托通常用于以下情况:
- 管理具有许多项目或行的列表、菜单或表格。
- 处理单页面应用程序中的动态内容。
- 通过避免为发生更改的元素附加和移除事件监听器来简化代码。
## 资源
- [MDN Web 文档关于事件委托](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_delegation)
- [JavaScript.info - 事件委托](https://javascript.info/event-delegation)

View File

@ -1,128 +0,0 @@
---
title: Explain `Function.prototype.bind`
---
## TL;DR
`Function.prototype.bind` is a method in JavaScript that allows you to create a new function with a specific `this` value and optional initial arguments. It's primary purpose is to:
- **Binding `this` value to preserve context**: The primary purpose of `bind` is to bind the `this` value of a function to a specific object. When you call `func.bind(thisArg)`, it creates a new function with the same body as `func`, but with `this` permanently bound to `thisArg`.
- **Partial application of arguments**: `bind` also allows you to pre-specify arguments for the new function. Any arguments passed to `bind` after `thisArg` will be prepended to the arguments list when the new function is called.
- **Method borrowing**: `bind` allows you to borrow methods from one object and apply them to another object, even if they were not originally designed to work with that object.
The `bind` method is particularly useful in scenarios where you need to ensure that a function is called with a specific `this` context, such as in event handlers, callbacks, or method borrowing.
---
## `Function.prototype.bind`
`Function.prototype.bind` allows you to create a new function with a specific `this` context and, optionally, preset arguments. `bind()` is most useful for preserving the value of `this` in methods of classes that you want to pass into other functions.
`bind` was frequently used on legacy React class component methods which were not defined using arrow functions.
```js
const john = {
age: 42,
getAge: function () {
return this.age;
},
};
console.log(john.getAge()); // 42
const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // undefined
const boundGetAge = john.getAge.bind(john);
console.log(boundGetAge()); // 42
const mary = { age: 21 };
const boundGetAgeMary = john.getAge.bind(mary);
console.log(boundGetAgeMary()); // 21
```
In the example above, when the `getAge` method is called without a calling object (as `unboundGetAge`), the value is `undefined` because the value of `this` within `getAge()` becomes the global object. `boundGetAge()` has its `this` bound to `john`, hence it is able to obtain the `age` of `john`.
We can even use `getAge` on another object which is not `john`! `boundGetAgeMary` returns the `age` of `mary`.
## Use cases
Here are some common scenarios where `bind` is frequently used:
### Preserving context and fixing the `this` value in callbacks
When you pass a function as a callback, the `this` value inside the function can be unpredictable because it is determined by the execution context. Using `bind()` helps ensure that the correct `this` value is maintained.
```js
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hello, my name is ${this.name}`);
},
};
const john = new Person('John Doe');
// Without bind(), `this` inside the callback will be the global object
setTimeout(john.greet, 1000); // Output: "Hello, my name is undefined"
// Using bind() to fix the `this` value
setTimeout(john.greet.bind(john), 2000); // Output: "Hello, my name is John Doe"
```
You can also use [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) to define class methods for this purpose instead of using `bind`. Arrow functions have the `this` value bound to its lexical context.
```js
class Person {
constructor(name) {
this.name = name;
}
greet = () => {
console.log(`Hello, my name is ${this.name}`);
};
}
const john = new Person('John Doe');
setTimeout(john.greet, 1000); // Output: "Hello, my name is John Doe"
```
### Partial application of functions (currying)
`bind` can be used to create a new function with some arguments pre-set. This is known as partial application or currying.
```js
function multiply(a, b) {
return a * b;
}
// Using bind() to create a new function with some arguments pre-set
const multiplyBy5 = multiply.bind(null, 5);
console.log(multiplyBy5(3)); // Output: 15
```
### Method borrowing
`bind` allows you to borrow methods from one object and apply them to another object, even if they were not originally designed to work with that object. This can be handy when you need to reuse functionality across different objects
```js
const person = {
name: 'John',
greet: function () {
console.log(`Hello, ${this.name}!`);
},
};
const greetPerson = person.greet.bind({ name: 'Alice' });
greetPerson(); // Output: Hello, Alice!
```
## Practice
Try [implementing your own `Function.prototype.bind()` method](/questions/javascript/function-bind) on GreatFrontEnd.
## Further Reading
- [Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)
- [Function Binding | javascript.info](https://javascript.info/bind)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-function-prototype-bind",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,42 +0,0 @@
---
title: Explique `Function.prototype.bind`
---
> O método `bind()` cria uma nova função que, quando chamada, tem sua palavra-chave `this` definida para o valor fornecido, com uma determinada sequência de argumentos precedendo qualquer um fornecido quando a nova função é chamada.
_Source: [Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)_
`bind()` é mais útil para vincular o valor do `this` em métodos de classes que você quer passar para outras funções. Isso foi frequentemente feito em métodos de classe de componente React que não foram definidos usando arrow functions.
```js
const john = {
age: 42,
getAge: function () {
return this.age;
},
};
console.log(john.getAge()); // 42
const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // undefined
const boundGetAge = john.getAge.bind(john);
console.log(boundGetAge()); // 42
const mary = { age: 21 };
const boundGetAgeMary = john.getAge.bind(mary);
console.log(boundGetAgeMary()); // 21
```
No exemplo acima, quando o método `getAge` é chamado sem um objeto chamado (como `unboundGetAge`), o valor é 'indefinido' porque o valor 'this' dentro de `getAge()` se torna o objeto global. `boundGetAge()` tem seu `this` ligado a `john`, portanto pode obter o `idade` de `john`.
Podemos até usar `getAge` em outro objeto que não é `john`! `boundGetAgeMary` retorna o `age` (idade) de `mary`.
## Prática
Tente [implementar seu próprio método `Function.prototype.bind()`](/questions/javascript/function-bind) na Great Front End.
## Referências
- [Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)

View File

@ -1,42 +0,0 @@
---
title: 解释 `Function.prototype.bind`
---
> `bind()`方法创建了一个新的函数,在被调用时,它有`this`关键字设置为提供的值。 具有在调用新函数时所提供的任何参数之前的特定序列。
_资料来源[Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)_
`bind()` 对于在要传递给其他函数的类的方法中绑定 `this` 的值非常有用。 这通常是在 React 类组件方法中做的,而这些方法没有使用箭头函数来定义。
```js
const john = {
age: 42,
getAge: function () {
return this.age;
},
};
console.log(john.getAge()); // 42
const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // undefined
const boundGetAge = john.getAge.bind(john);
console.log(boundGetAge()); // 42
const mary = { age: 21 };
const boundGetAgeMary = john.getAge.bind(mary);
console.log(boundGetAgeMary()); // 21
```
在上面的例子中,当`getAge`方法被调用时没有一个调用对象(如`unboundGetAge` 值为 `undefined` ,因为`getAge()` 里的 `this` 值变成了全局对象。 `boundGetAge()` 将其`this` 绑定到`john`,因此它能够获得`john`的`age`。
我们甚至可以在另一个不是`john`的对象上使用 `getAge`! `boundGetAgeMary` 返回 `mary` 的`age` 。
## 练习
在 GreatFrontEnd 尝试[实现你自己的 `Function.prototype.bind()` 方法](/questions/javascript/function-bind)。
## 参考资料
- [Function.prototype.bind() - JavaScript | MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind)

View File

@ -1,139 +0,0 @@
---
title: Explain "hoisting"
---
## TL;DR
- **Variable declarations (`var`)**: Declarations are hoisted, but not initializations. The value of the variable is `undefined` if accessed before initialization.
- **Variable declarations (`let` and `const`)**: Declarations are hoisted, but not initialized. Accessing them results in `ReferenceError` until the actual declaration is encountered.
- **Function expressions (`var`)**: Declarations are hoisted, but not initializations. The value of the variable is `undefined` if accessed before initialization.
- **Function declarations (`function`)**: Both declaration and definition are fully hoisted.
- **Class declarations (`class`)**: Declarations are hoisted, but not initialized. Accessing them results in `ReferenceError` until the actual declaration is encountered.
- **Import declarations (`import`)**: Declarations are hoisted, and side effects of importing the module are executed before the rest of the code.
The following behavior summarizes the result of accessing the variables before they are declared.
| Declaration | Accessing before declaration |
| ------------------------------ | ---------------------------- |
| `var foo` | `undefined` |
| `let foo` | `ReferenceError` |
| `const foo` | `ReferenceError` |
| `class Foo` | `ReferenceError` |
| `var foo = function() { ... }` | `undefined` |
| `function foo() { ... }` | Normal |
| `import` | Normal |
---
## Hoisting
Hoisting is a term used to explain the behavior of variable declarations in your code. Variables declared or initialized with the `var` keyword will have their declaration "moved" up to the top of their containing scope during compilation, which we refer to as hoisting.
Only the declaration is hoisted, the initialization/assignment (if there is one), will stay where it is. Note that the declaration is not actually moved the JavaScript engine parses the declarations during compilation and becomes aware of variables and their scopes, but it is easier to understand this behavior by visualizing the declarations as being "hoisted" to the top of their scope.
Let's explain with a few code samples. Note that the code for these examples should be executed within a module scope instead of being entered line by line into a REPL like the browser console.
### Hoisting of variables declared using `var`
Hoisting is seen in action here as even though `foo` is declared and initialized after the first `console.log()`, the first `console.log()` prints the value of `foo` as `undefined`.
```js
console.log(foo); // undefined
var foo = 1;
console.log(foo); // 1
```
You can visualize the code as:
```js
var foo;
console.log(foo); // undefined
foo = 1;
console.log(foo); // 1
```
### Hoisting of variables declared using `let`, `const`, and `class`
Variables declared via `let`, `const`, and `class` are hoisted as well. However, unlike `var` and `function`, they are not initialized and accessing them before the declaration will result in a `ReferenceError` exception. The variable is in a "temporal dead zone" from the start of the block until the declaration is processed.
```js
y; // ReferenceError: Cannot access 'y' before initialization
let y = 'local';
```
```js
z; // ReferenceError: Cannot access 'z' before initialization
const z = 'local';
```
```js
Foo; // ReferenceError: Cannot access 'Foo' before initialization
class Foo {
constructor() {}
}
```
### Hoisting of function expressions
Function expressions are functions written in the form of variable declarations. Since they are also declared using `var`, only the variable declaration is hoisted.
```js
console.log(bar); // undefined
bar(); // Uncaught TypeError: bar is not a function
var bar = function () {
console.log('BARRRR');
};
```
### Hoisting of function declarations
Function declarations use the `function` keyword. Unlike function expressions, function declarations have both the declaration and definition hoisted, thus they can be called even before they are declared.
```js
console.log(foo); // [Function: foo]
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
```
The same applies to generators (`function*`), async functions (`async function`), and async function generators (`async function*`).
### Hoisting of `import` statements
Import declarations are hoisted. The identifiers the imports introduce are available in the entire module scope, and their side effects are produced before the rest of the module's code runs.
```js
foo.doSomething(); // Works normally.
import foo from './modules/foo';
```
## Under the hood
In reality, JavaScript creates all variables in the current scope before it even tries to executes the code. Variables created using `var` keyword will have the value of `undefined` where variables created using `let` and `const` keywords will be marked as `<value unavailable>`. Thus, accessing them will cause a `ReferenceError` preventing you to access them before initialization.
In ECMAScript specifications `let` and `const` declarations are [explained as below](https://tc39.es/ecma262/#sec-let-and-const-declarations):
> The variables are created when their containing Environment Record is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated.
However, this statement is [a litle bit different for the `var` keyword](https://tc39.es/ecma262/#sec-variable-statement):
> Var variables are created when their containing Environment Record is instantiated and are initialized to `undefined` when created.
## Modern practices
In practice, modern code bases avoid using `var` and use `let` and `const` exclusively. It is recommended to declare and initialize your variables and import statements at the top of the containing scope/module to eliminate the mental overhead of tracking when a variable can be used.
ESLint is a static code analyzer that can find violations of such cases with the following rules:
- [`no-use-before-define`](https://eslint.org/docs/latest/rules/no-use-before-define): This rule will warn when it encounters a reference to an identifier that has not yet been declared.
- [`no-undef`](https://eslint.org/docs/latest/rules/no-undef): This rule will warn when it encounters a reference to an identifier that has not yet been declared.
## Further reading
- [Hoisting | MDN](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [JavaScript Visualized: Hoisting](https://dev.to/lydiahallie/javascript-visualized-hoisting-478h)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-hoisting",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "hard"
}

View File

@ -1,42 +0,0 @@
---
title: Explique "hoisting"
---
Hoisting é um termo usado para explicar o comportamento de declarações variáveis em seu código. Variáveis declaradas ou inicializadas com a palavra-chave `var` terão sua declaração "movida" até o topo do escopo do módulo/função do escopo, a que chamamos de hoisting. No entanto, apenas a declaração está hoisted, a atribuição (se houver uma), ficará onde está.
Observe que a declaração não é realmente movida - o motor de JavaScript analisa as declarações durante a compilação e torna-se ciente das declarações e dos seus âmbitos. É mais fácil compreender este comportamento, visualizando as declarações como sendo hoisted até ao topo do seu escopo. Vamos explicar com alguns exemplos.
```js
console.log(foo); // indefinido
var foo = 1;
console.log(foo); // 1
```
As declarações de função têm o corpo hoisted enquanto as expressões da função (escritas na forma de declarações variáveis) só tem a declaração da variável hoisted.
```js
// Declaração de função
console.log(foo); // [Function: foo]
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
console.log(foo); // [Function: foo]
// Function Expression
console.log(bar); // undefined
bar(); // Uncaught TypeError: bar is not a function
var bar = function () {
console.log('BARRRR');
};
console.log(bar); // [Function: bar]
```
Variáveis declaradas via `let` e `const` também sofrem o hoisted. No entanto, ao contrário de `var` e `function`, eles não são inicializados e acessá-los antes que a declaração resulte em uma exceção `ReferenceError`. A variável está em uma "zona temporária morta" desde o início do bloco até que a declaração seja processada.
```js
x; // undefined; // Erro de referência: y não está definido
var x = 'local';
let y = 'local';
```

View File

@ -1,43 +0,0 @@
---
title: 解释“(变量)提升”
---
提升是用于解释你代码中变量声明行为的一个术语。 使用`var`关键字声明或初始化的变量将会将其声明“移动”到其模块/函数级别范围的顶端。 我们把它成为变量提升。 然而,只有声明被提升,赋值(如果有的话)将留在原地。
请注意,声明实际上并没有被移动--JavaScript 引擎在编译过程中解析了声明,并意识到了声明及其作用域。 通过视觉将声明置于其作用域之首,更容易理解这种行为。 让我们用几个例子来解释。
```js
console.log(foo); // undefined
var foo = 1;
console.log(foo); // 1
```
函数声明的主体提升到顶端,而函数表达式(以变量声明的形式写成) 只有变量声明被提升到顶端。
```js
// Function Declaration
console.log(foo); // [Function: foo]
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
console.log(foo); // [Function: foo]
// Function Expression
console.log(bar); // undefined
bar(); // Uncaught TypeError: bar is not a function
var bar = function () {
console.log('BARRRR');
};
console.log(bar); // [Function: bar]
```
通过 `let` 和 `const` 声明的变量也被提升。 然而,与`var` 和 `function`不同的是,在声明导致`ReferenceError` 例外之前,它们没有初始化并访问它们。 该变量处于从代码块开始直到声明被处理时的一个“暂时性死区”。
```js
x; // undefined
y; // Reference error: y is not defined
var x = 'local';
let y = 'local';
```

View File

@ -1,29 +0,0 @@
---
title: Explain how JSONP works (and how it's not really Ajax)
---
JSONP (JSON with Padding) is a method commonly used to bypass the cross-domain policies in web browsers because Ajax requests from the current page to a cross-origin domain is not allowed.
JSONP works by making a request to a cross-origin domain via a `<script>` tag and usually with a `callback` query parameter, for example: `https://example.com?callback=printData`. The server will then wrap the data within a function called `printData` and return it to the client.
```html
<!-- https://mydomain.com -->
<script>
function printData(data) {
console.log(`My name is ${data.name}!`);
}
</script>
<script src="https://example.com?callback=printData"></script>
```
```js
// File loaded from https://example.com?callback=printData
printData({ name: 'John Doe' });
```
The client has to have the `printData` function in its global scope and the function will be executed by the client when the response from the cross-origin domain is received.
JSONP can be unsafe and has some security implications. As JSONP is really JavaScript, it can do everything else JavaScript can do, so you need to trust the provider of the JSONP data.
These days, [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) is the recommended approach and JSONP is seen as a hack.

View File

@ -1,11 +0,0 @@
{
"slug": "explain-how-jsonp-works-and-how-its-not-really-ajax",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "network", "security"],
"importance": "mid",
"difficulty": "hard"
}

View File

@ -1,29 +0,0 @@
---
title: Explique como o JSONP funciona (e como ele não é Ajax)
---
O JSONP (JSON com padding) é um método comumente utilizado para contornar as políticas de domínio cruzado em navegadores web, porque solicitações Ajax da página atual para um domínio de origem cruzada não são permitidas.
O JSONP funciona fazendo uma solicitação a um domínio cross-origin através de uma tag `<script>` e geralmente com um parâmetro de consulta `callback`, por exemplo: `https://example O?callback=printData`. O servidor irá, então, encapsular os dados em uma função chamada printData e enviá-la de volta ao cliente.
```html
<!-- https://mydomain.com -->
<script>
function printData(data) {
console.log(`My name is ${data.name}!`);
}
</script>
<script src="https://example.com?callback=printData"></script>
```
```js
// Arquivo carregado de https://example.com?callback=printData
printData({ name: 'John Doe' });
```
O cliente deve ter a função `printData` no seu escopo global e a função será executada pelo cliente quando a resposta do domínio de origem cruzada for recebida.
O JSONP pode ser inseguro e tem algumas implicações de segurança. Como o JSONP é JavaScript, ele pode fazer tudo o que o JavaScript pode fazer, então você precisa confiar no provedor dos dados JSONP.
Hoje em dia, [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) é a abordagem recomendada, e a JSONP é vista como um hack.

View File

@ -1,29 +0,0 @@
---
title: 解释JSONP 如何工作(以及它为什么不是真正的 Ajax)
---
JSONP (JSON with Padding) 是一种通常用来绕过网络浏览器中的跨域策略的方法,因为不允许从当前页面的 Ajax 请求到跨源域。
JSONP 工作方式是通过一个 `<script>` 标签向一个跨源域提出请求,通常使用一个 `callback` 查询参数, 例如:`https://example.com?callback=printData`。 然后,服务器将把数据填充到一个名为 `printData` 的函数中,然后返回给客户端。
```html
<!-- https://mydomain.com -->
<script>
function printData(data) {
console.log(`My name is ${data.name}!`);
}
</script>
<script src="https://example.com?callback=printData"></script>
```
```js
// 从 https://example.com?callback=printData 加载的文件
printData({ name: 'John Doe' });
```
客户端必须将`printData`函数设在其全局范围内,当收到跨源域的响应时,该函数将由客户端执行。
JSONP 可能是不安全的,并涉及一些安全问题。 因为 JSONP 真的是 JavaScript它可以做所有其它 JavaScript 可以做的事情,所以你需要信任 JSONP 数据的提供者。
目前前端开发领域,[CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 是推荐的方法JSONP 被视为一种 hack破解

View File

@ -1,178 +0,0 @@
---
title: Explain how prototypal inheritance works
---
## TL;DR
Prototypical inheritance in JavaScript is a way for objects to inherit properties and methods from other objects. Every JavaScript object has a special hidden property called `[[Prototype]]` (commonly accessed via `__proto__` or using `Object.getPrototypeOf()`) that is a reference to another object, which is called the object's "prototype". When a property is accessed on an object and if the property is not found on that object, the JavaScript engine looks at the object's `__proto__`, and the `__proto__`'s `__proto__` and so on, until it finds the property defined on one of the `__proto__`s or until it reaches the end of the prototype chain. This behavior simulates classical inheritance, but it is really more of [delegation than inheritance](https://davidwalsh.name/javascript-objects).
## Example of Prototypal Inheritance
```js
// Parent object constructor.
function Animal(name) {
this.name = name;
}
// Add a method to the parent object's prototype.
Animal.prototype.makeSound = function () {
console.log('The ' + this.constructor.name + ' makes a sound.');
};
// Child object constructor.
function Dog(name) {
Animal.call(this, name); // Call the parent constructor.
}
// Set the child object's prototype to be the parent's prototype.
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
// Add a method to the child object's prototype.
Dog.prototype.bark = function () {
console.log('Woof!');
};
// Create a new instance of Dog.
const bolt = new Dog('Bolt');
// Call methods on the child object.
console.log(bolt.name); // "Bolt"
bolt.makeSound(); // "The Dog makes a sound."
bolt.bark(); // "Woof!"
```
Things to note are:
- `.makeSound` is not defined on `Dog`, so the JavaScript engine goes up the prototype chain and finds `.makeSound` on the inherited `Animal`.
- Using `Object.create()` to build the inheritance chain is no longer recommended. Use `Object.setPrototypeOf()` instead.
---
## Prototypical Inheritance in Javascript
Prototypical inheritance is a feature in JavaScript used to create objects that inherit properties and methods from other objects. Instead of a class-based inheritance model, JavaScript uses a prototype-based model, where objects can directly inherit from other objects.
### Key Concepts
1. **Prototypes** : Every object in Javascript has a prototype, which is another object. When you create an object using an object literal or a constructor function, the new object is linked to the prototype of its constructor function or the `Object.prototype` if no prototype is specified. This is commonly referenced using `__proto__` or `[[Prototype]]`. You can also get the prototype by using inbuilt method `Object.getPrototypeOf()` and you can set the prototype of an object via `Object.setPrototypeOf()`.
```js
// Define a constructor function
function Person(name, age) {
this.name = name;
this.age = age;
}
// Add a method to the prototype
Person.prototype.sayHello = function () {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
// Create a new object using the constructor function
let john = new Person('John', 30);
// The new object has access to the methods defined on the prototype
john.sayHello(); // "Hello, my name is John and I am 30 years old."
// The prototype of the new object is the prototype of the constructor function
console.log(john.__proto__ === Person.prototype); // true
// You can also get the prototype using Object.getPrototypeOf()
console.log(Object.getPrototypeOf(john) === Person.prototype); // true
// You can set the prototype of an object using Object.setPrototypeOf()
let newProto = {
sayGoodbye: function () {
console.log(`Goodbye, my name is ${this.name}`);
},
};
Object.setPrototypeOf(john, newProto);
// Now john has access to the methods defined on the new prototype
john.sayGoodbye(); // "Goodbye, my name is John"
// But no longer has access to the methods defined on the old prototype
console.log(john.sayHello); // undefined
```
2. **Prototype chain**: When a property or method is accessed on an object, JavaScript first looks for it on the object itself. If it doesn't find it there, it looks at the object's prototype, and then the prototype's prototype, and so on, until it either finds the property or reaches the end of the chain (i.e., `null`).
3. **Constructor functions**: JavaScript provides constructor functions to create objects. When a function is used as a constructor with the new keyword, the new object's prototype (`[[Prototype]]`) is set to the constructor's prototype property.
```js
// Define a constructor function
function Animal(name) {
this.name = name;
}
// Add a method to the prototype
Animal.prototype.sayName = function () {
console.log(`My name is ${this.name}`);
};
// Define a new constructor function
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
// Set the prototype of Dog to be a new instance of Animal
Dog.prototype = Object.create(Animal.prototype);
// Add a method to the Dog prototype
Dog.prototype.bark = function () {
console.log('Woof!');
};
// Create a new object using the Dog constructor function
let fido = new Dog('Fido', 'Labrador');
// The new object has access to the methods defined on its own prototype and the Animal prototype
fido.bark(); // "Woof!"
fido.sayName(); // "My name is Fido"
// If we try to access a method that doesn't exist on the Dog prototype or the Animal prototype, JavaScript will return undefined
console.log(fido.fly); // undefined
```
4. **`Object.create()`**: This method creates a new object with the specified prototype object and properties. It's a straightforward way to set up prototypical inheritance. If you create a object via `Object.create(null)` it will not inherit any properties from `Object.prototype`. This means the object will not have any built-in properties or methods like `toString()`, `hasOwnProperty()`,
```js
// Define a prototype object
let proto = {
greet: function () {
console.log(`Hello, my name is ${this.name}`);
},
};
// Use `Object.create()` to create a new object with the specified prototype
let person = Object.create(proto);
person.name = 'John';
// The new object has access to the methods defined on the prototype
person.greet(); // "Hello, my name is John"
// Check if the object has a property
console.log(person.hasOwnProperty('name')); // true
// Create an object that does not inherit from Object.prototype
let animal = Object.create(null);
animal.name = 'Rocky';
// The new object does not have any built-in properties or methods
console.log(animal.toString); // undefined
console.log(animal.hasOwnProperty); // undefined
// But you can still add and access custom properties
animal.describe = function () {
console.log(`Name of the animal is ${this.name}`);
};
animal.describe(); // "Name of the animal is Rocky"
```
## Resources
- [Inheritance and the prototype chain | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)
- [JavaScript Visualized: Prototypal Inheritance](https://dev.to/lydiahallie/javascript-visualized-prototypal-inheritance-47co)

View File

@ -1,12 +0,0 @@
{
"slug": "explain-how-prototypal-inheritance-works",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "medium",
"ranking": 1
}

View File

@ -1,49 +0,0 @@
---
title: Explique como funciona a herança de protótipos
---
Essa é uma pergunta extremamente comum em entrevistas de JavaScript. Todos os objetos JavaScript têm uma propriedade `__proto__` com exceção de objetos criados com `object.create(null)`, ou seja, uma referência a outro objeto, que é chamado de "protótipo" do objeto. Quando uma propriedade é acessada em um objeto e se a propriedade não é encontrada nesse objeto, o motor de JavaScript olha para o objeto `__proto__`, e o `__proto__` do `__proto__` e assim por diante, até que encontre a propriedade definida em um dos `__proto__`s ou até chegar ao final da cadeia de protótipos. Este comportamento simula a herança clássica, mas é realmente mais de [delegação do que herança](https://davidwalsh.name/javascript-objects).
## Exemplo de Herança de Protótipos
```js
// Construtor de objeto pai.
function Animal(name) {
this.name = name;
}
// Adiciona um método ao protótipo do objeto pai.
Animal.prototype.makeSound = function () {
console.log('O ' + this.constructor.name + ' faz um som.');
};
// Construtor filho.
function Dog(name) {
Animal.call(this, name); // Chama o construtor pai.
}
// Set the child object's prototype to be the parent's prototype.
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
// Adiciona um método ao protótipo do objeto filho.
Dog.prototype.bark = function () {
console.log('Woof!');
};
// Criar uma nova instância do Cachorro.
const bolt = new Dog('Bolt');
// Chama métodos no objeto filho.
console.log(bolt.name); // "Bolt"
bolt.makeSound(); // "O Dog faz um som."
bolt.bark(); // "Woof!"
```
As coisas a observar são:
- `.makeSound` não está definido em `Dog`, então o navegador aumenta a cadeia de protótipos e encontra `.makeSound` para fora do `Animal` herdado.
- Using `Object.create` to build the inheritance chain is no longer recommended. Use `Object.setPrototypeOf` instead.
## Resources
- [Inheritance and the prototype chain | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)

View File

@ -1,49 +0,0 @@
---
title: 解释原型继承如何工作
---
这是一个极其常见的 JavaScript 面试问题。 所有 JavaScript 对象(用`Object.create(null)` 创建的对象除外)都有一个 `__proto__` 属性,是指另一个对象,它叫做对象的“原型”。 当一个属性在一个对象上被访问时,如果该属性未在该对象上被找到, JavaScript 引擎看看对象的 `__proto__`、 `__proto__` 的 `__proto__` 等,直到它在一个 `__proto__`中找到定义的属性或直到它到达原型链的末尾。 这种行为模拟传统继承,但它实际上更多是[委托而不是继承](https://davidwalsh.name/javascript-objects)。
## 原型继承的例子
```js
// Parent object constructor.
function Animal(name) {
this.name = name;
}
// Add a method to the parent object's prototype.
Animal.prototype.makeSound = function () {
console.log('The ' + this.constructor.name + ' makes a sound.');
};
// Child object constructor.
function Dog(name) {
Animal.call(this, name); // Call the parent constructor.
}
// Set the child object's prototype to be the parent's prototype.
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
// Add a method to the child object's prototype.
Dog.prototype.bark = function () {
console.log('Woof!');
};
// Create a new instance of Dog.
const bolt = new Dog('Bolt');
// Call methods on the child object.
console.log(bolt.name); // "Bolt"
bolt.makeSound(); // "The Dog makes a sound."
bolt.bark(); // "Woof!"
```
需要注意的是:
- `.makeSound` 没有定义在`Dog`上,因此引擎会在继承的原型链`Animal`上发现`.makeSound`。
- Using `Object.create` to build the inheritance chain is no longer recommended. Use `Object.setPrototypeOf` instead.
## Resources
- [Inheritance and the prototype chain | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain)

View File

@ -1,18 +0,0 @@
---
title: Explain how `this` works in JavaScript
---
There's no simple explanation for `this`; it is one of the most confusing concepts in JavaScript. A hand-wavey explanation is that the value of `this` depends on how the function is called. Having read many explanations on `this` online, [Arnav Aggrawal](https://medium.com/@arnav_aggarwal)'s explanation was the clearest. The following rules are applied:
1. If the `new` keyword is used when calling the function, `this` inside the function is a brand new object.
1. If `apply`, `call`, or `bind` are used to call/create a function, `this` inside the function is the object that is passed in as the argument.
1. If a function is called as a method, such as `obj.method()` — `this` is the object that the function is a property of.
1. If a function is invoked as a free function invocation, meaning it was invoked without any of the conditions present above, `this` is the global object. In a browser, it is the `window` object. If in strict mode (`'use strict'`), `this` will be `undefined` instead of the global object.
1. If multiple of the above rules apply, the rule that is higher wins and will set the `this` value.
1. If the function is an ES2015 arrow function, it ignores all the rules above and receives the `this` value of its surrounding scope at the time it is created.
For an in-depth explanation, do check out his [article on Medium](https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3).
#### Can you give an example of one of the ways that working with this has changed in ES2015?
ES2015 allows you to use [arrow functions](http://2ality.com/2017/12/alternate-this.html#arrow-functions) which uses the [enclosing lexical scope](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this). This is usually convenient, but does prevent the caller from controlling context via `.call` or `.apply`—the consequences being that a library such as `jQuery` will not properly bind `this` in your event handler functions. Thus, it's important to keep this in mind when refactoring large legacy applications.

View File

@ -1,13 +0,0 @@
{
"slug": "explain-how-this-works-in-javascript",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "hard",
"featured": true,
"ranking": 1
}

View File

@ -1,18 +0,0 @@
---
title: Explique como `this` funciona em JavaScript
---
Não há uma explicação simples para `this`; ela é um dos conceitos mais confusos do JavaScript. Uma explicação superficial é que o valor do `this` depende de como a função é chamada. Tendo lido muitas explicações sobre `this` online, [Arnav Aggrawal](https://medium.com/@arnav_aggarwal) é a explicação que foi mais clara. As seguintes regras se aplicam:
1. Se a palavra-chave `new` é usada ao chamar a função, `new` dentro da função é um objeto totalmente novo.
2. Se `apply`, `call`, ou `bind` forem usados para chamar/criar uma função, `this` dentro da função é o objeto passado como o argumento.
3. Se uma função é chamada como um método, como `obj.method()` — `this` é o objeto do qual a função é uma propriedade.
4. Se uma função é chamada como uma chamada de função livre, significando que ele foi invocado sem nenhuma das condições presentes acima, `this` é o objeto global. Em um navegador, é o objeto `window`. Se em modo estrito (`'use strict'`), `this` será `undefined` em vez do objeto global.
5. Se se aplicarem múltiplas das regras acima, a regra que é maior ganha e definirá o valor `this`.
6. Se a função é uma arrow function ES2015, ela ignora todas as regras acima e recebe o valor `this` do seu escopo circundante no momento em que ele é criado.
Para uma explicação aprofundada, confira o [artigo na Medium](https://codeburst.io/the-simple-rules-to-this-in-javascript-35d97f31bde3).
#### Você pode dar um exemplo de uma das maneiras como o trabalho com "this" mudou no ES2015?
ES2015 permite que você use [arrow functions](http://2ality.com/2017/12/alternate-this.html#arrow-functions) que usa o [enclosing lexical scope](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this). Isso geralmente é conveniente, mas impede quem chamou de controlar o contexto através de `.call` ou `.apply`—as consequências são que uma biblioteca como `jQuery` não irá vincular corretamente o `this` em suas funções de manipulador de eventos. Portanto, é importante ter isso em mente ao refatorar grandes aplicações legadas.

View File

@ -1,18 +0,0 @@
---
title: 解释 JavaScript `this` 如何工作
---
`this`没有简单的解释;它是 JavaScript 中最令人困惑的概念之一。 一个简短的解释是,`this`的值取决于函数如何调用。 在线阅读了很多关于`this`的解释,[Arnav Aggrawal](https://med.com/@arnav_aggarwal)的解释很清楚。 适用下列规则:
1. 如果调用函数时使用 `new` 关键字,那么函数中的`this` 是一个全新的对象。
2. 如果`apply`, `call`, 或 `bind` 用于调用/创建函数, 那么函数中的`this` 是作为参数传递的对象。
3. 如果一个函数作为方法被调用,例如`obj.method()` -- `this`是该函数的一个属性对象。
4. 如果一个函数被作为一个自由函数调用, 意思是在没有上述任何条件的情况下调用它,`this `就是全局对象。 在浏览器中,它是 `window ` 对象。 如果在严格模式下(`'use strict'`)`this`将是`undefined ` 而不是全局对象。
5. 如果上述多条规则都适用,则排名靠前的规则获胜,并将设置`this`值。
6. 如果函数是一个 ES2015 箭头函数, 它将无视上面的所有规则,并在创建时接收其周围范围的`this`值。
若要深入解释,请查阅他的[Medium 上面的文章]\(https://codeburst.io/the-simple-rules-this in javascript-35d97f31bde3)。
#### 你能否举例说明在 ES2015 年处理这一问题的方式已经发生变化?
ES2015 允许您使用[箭头函数](http://2ality.com/2017/12/alternate-this.html#arrow-functions)来使用[封闭的词汇范围](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this). 这通常很方便,但确实阻止了调用者通过`.call`或`.apply`控制上下文--后果是诸如`jQuery`这样的库不会在你的事件处理函数中正确绑定`this`。 因此,在重构大型遗留应用程序时必须牢记这一点。

View File

@ -1,238 +0,0 @@
---
title: Explain the difference between mutable and immutable objects
---
## TL;DR
**Mutable objects** allow for modification of properties and values after creation, which is the default behavior for most objects.
```js
const mutableObject = {
name: 'John',
age: 30,
};
// Modify the object
mutableObject.name = 'Jane';
// The object has been modified
console.log(mutableObject); // Output: { name: 'Jane', age: 30 }
```
**Immutable objects** cannot be directly modified after creation. Its content cannot be changed without creating an entirely new value.
```js
const immutableObject = Object.freeze({
name: 'John',
age: 30,
});
// Attempt to modify the object
immutableObject.name = 'Jane';
// The object remains unchanged
console.log(immutableObject); // Output: { name: 'John', age: 30 }
```
The key difference between mutable and immutable objects is modifiability. Immutable objects cannot be modified after they are created, while mutable objects can be.
---
## Immutability
Immutability is a core principle in functional programming but it has lots to offer to object-oriented programs as well.
### Mutable objects
Mutability refers to the ability of an object to have its properties or elements changed after it's created. A mutable object is an object whose state can be modified after it is created. In JavaScript, objects and arrays are mutable by default. They store references to their data in memory. Changing a property or element modifies the original object. Here is an example of a mutable object:
```js
const mutableObject = {
name: 'John',
age: 30,
};
// Modify the object
mutableObject.name = 'Jane';
// The object has been modified
console.log(mutableObject); // Output: { name: 'Jane', age: 30 }
```
### Immutable objects
An immutable object is an object whose state cannot be modified after it is created. Here is an example of an immutable object:
```js
const immutableObject = Object.freeze({
name: 'John',
age: 30,
});
// Attempt to modify the object
immutableObject.name = 'Jane';
// The object remains unchanged
console.log(immutableObject); // Output: { name: 'John', age: 30 }
```
Primitive data types like numbers, strings, booleans, `null`, and `undefined` are inherently immutable. Once assigned a value, you cannot directly modify them.
```js
let name = 'Alice';
name.toUpperCase(); // This won't modify the original name variable
console.log(name); // Still prints "Alice"
// To change the value, you need to reassign a new string
name = name.toUpperCase();
console.log(name); // Now prints "ALICE"
```
Some built-in immutable JavaScript objects are `Math`, `Date` but custom objects are generally mutable.
### `const` vs immutable objects
A common confusion / misunderstanding is that declaring a variable using `const` makes the value immutable, which is not true at all.
`const` prevents reassignment of the variable itself, but does not make the value it holds immutable. This means:
- For primitive values (numbers, strings, booleans), `const` makes the value immutable since primitives are immutable by nature.
- For non-primitive values like objects and arrays, `const` only prevents reassigning a new object/array to the variable, but the properties/elements of the existing object/array can still be modified.
On the other hand, an immutable object is an object whose state (properties and values) cannot be modified after it is created. This is achieved by using methods like `Object.freeze()` which makes the object immutable by preventing any changes to its properties.
```js
// Using const
const person = { name: 'John' };
person = { name: 'Jane' }; // Error: Assignment to constant variable
person.name = 'Jane'; // Allowed, person.name is now 'Jane'
// Using Object.freeze() to create an immutable object
const frozenPerson = Object.freeze({ name: 'John' });
frozenPerson.name = 'Jane'; // Fails silently (no error, but no change)
frozenPerson = { name: 'Jane' }; // Error: Assignment to constant variable
```
In the first example with `const`, reassigning a new object to `person` is not allowed, but modifying the `name` property is permitted. In the second example, `Object.freeze()` makes the `frozenPerson` object immutable, preventing any changes to its properties.
It's important to note that `Object.freeze()` creates a shallow immutable object. If the object contains nested objects or arrays, those nested data structures are still mutable unless frozen separately.
Therefore, while `const` provides immutability for primitive values, creating truly immutable objects requires using `Object.freeze()` or other immutability techniques like deep freezing or using immutable data structures from libraries like [Immer](https://immerjs.github.io/immer/) or [Immutable.js](https://immutable-js.com/).
## Various ways to implement immutability in plain JavaScript objects
Here are a few ways to add/simulate different forms of immutability in plain JavaScript objects.
### Immutable object properties
By combining `writable: false` and `configurable: false`, you can essentially create a constant (cannot be changed, redefined or deleted) as an object property, like:
```js
const myObject = {};
Object.defineProperty(myObject, 'number', {
value: 42,
writable: false,
configurable: false,
});
console.log(myObject.number); // 42
myObject.number = 43;
console.log(myObject.number); // 42
```
### Preventing extensions on objects
If you want to prevent an object from having new properties added to it, but otherwise leave the rest of the object's properties alone, call `Object.preventExtensions(...)`:
```js
let myObject = {
a: 2,
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
```
In non-strict mode, the creation of `b` fails silently. In strict mode, it throws a `TypeError`.
### Sealing an object
`Object.seal()` creates a "sealed" object, which means it takes an existing object and essentially calls `Object.preventExtensions()` on it, but also marks all its existing properties as `configurable: false`. Therefore, not only can you not add any more properties, but you also cannot reconfigure or delete any existing properties, though you can still modify their values.
```js
// Create an object
const person = {
name: 'John Doe',
age: 30,
};
// Seal the object
Object.seal(person);
// Try to add a new property (this will fail silently)
person.city = 'New York'; // This has no effect
// Try to delete an existing property (this will fail silently)
delete person.age; // This has no effect
// Modify an existing property (this will work)
person.age = 35;
console.log(person); // Output: { name: 'John Doe', age: 35 }
// Try to re-configure an existing property descriptor (this will fail)
Object.defineProperty(person, 'name', { writable: false }); // TypeError: Cannot redefine property: name
// Check if the object is sealed
console.log(Object.isSealed(person)); // Output: true
```
### Freezing an object
`Object.freeze()` creates a frozen object, which means it takes an existing object and essentially calls `Object.seal()` on it, but it also marks all "data accessor" properties as writable:false, so that their values cannot be changed.
This approach is the highest level of immutability that you can attain for an object itself, as it prevents any changes to the object or to any of its direct properties (though, as mentioned above, the contents of any referenced other objects are unaffected).
```js
let immutableObject = Object.freeze({});
```
Freezing an object does not allow new properties to be added to an object and prevents users from removing or altering the existing properties. `Object.freeze()` preserves the enumerability, configurability, writability and the `prototype` of the object. It returns the passed object and does not create a frozen copy.
`Object.freeze()` makes the object immutable. However, it is not necessarily constant. `Object.freeze` prevents modifications to the object itself and its direct properties, nested objects within the frozen object can still be modified.
```js
let obj = {
user: {},
};
Object.freeze(obj);
obj.user.name = 'John';
console.log(obj.user.name); //Output: 'John'
```
## What are the pros and cons of immutability?
### Pros
- **Easier change detection**: Object equality can be determined in a performant and easy manner through referential equality. This is useful for comparing object differences in React and Redux.
- **Less complicated**: Programs with immutable objects are less complicated to think about, since you don't need to worry about how an object may evolve over time.
- Easy sharing via references: One copy of an object is just as good as another, so you can cache objects or reuse the same object multiple times.
- **Thread-safe**: Immutable objects can be safely used between threads in a multi-threaded environment since there is no risk of them being modified in other concurrently running threads. In the most cases, JavaScript runs in a single-threaded environment
- **Less memory needed**: Using libraries like [Immer](https://immerjs.github.io/immer/) and [Immutable.js](https://immutable-js.com/), objects are modified using structural sharing and less memory is needed for having multiple objects with similar structures.
- **No need for defensive copying**: Defensive copies are no longer necessary when immutable objects are returning from or passed to functions, since there is no possibility an immutable object will be modified by it.
### Cons
- **Complex to create yourself**: Naive implementations of immutable data structures and its operations can result in extremely poor performance because new objects are created each time. It is recommended to use libraries for efficient immutable data structures and operations that leverage on structural sharing.
- **Potential negative performance**: Allocation (and deallocation) of many small objects rather than modifying existing ones can cause a performance impact. The complexity of either the allocator or the garbage collector usually depends on the number of objects on the heap.
- **Complexity for cyclic data structures**: Cyclic data structures such as graphs are difficult to implement.
## Further reading
- [Object.defineProperty() | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty)
- [Object.freeze() | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze)
- [Object.seal() | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/seal)
- [Object.preventExtensions() | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/preventExtensions)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-the-difference-between-mutable-and-immutable-objects",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "mid",
"difficulty": "medium"
}

View File

@ -1,81 +0,0 @@
---
title: Explique a diferença entre objetos mutáveis e imutáveis
---
A imutabilidade é um princípio central na programação funcional e também tem muito a oferecer para programas orientados para objetos. Um objeto mutável é um objeto cujo estado pode ser modificado depois de criado. Um objeto mutável é um objeto cujo estado pode ser modificado depois de criado.
## O que é um exemplo de um objeto imutável em JavaScript?
Em JavaScript, alguns tipos internos (números, strings) são imutáveis, mas objetos personalizados geralmente são mutáveis.
Alguns objetos JavaScript imutáveis integrados são `Math`, `Date`.
Aqui estão algumas maneiras de adicionar/simular imutabilidade em objetos JavaScript simples.
### Propriedades Constante de Objeto
Ao combinar `gravável: falso` e `configurável: falso`, você pode criar uma constante (não pode ser alterada, redefinida ou apagada) como uma propriedade do objeto, como:
```js
let myObject = {};
Object.defineProperty(myObject, 'number', {
value: 42,
writable: false,
configurable: false,
});
console.log(myObject.number); // 42
myObject.number = 43;
console.log(myObject.number); // 42
```
### Evitar Extensões
Se você quiser evitar que um objeto tenha novas propriedades adicionadas, mas deixando o resto das propriedades do objeto sozinhas, chame `Object.preventExtensions(...)`:
```js
let myObject = {
a: 2,
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
```
No modo não restrito, a criação de `b` falha silenciosamente. No modo estrito, ele lança um `TypeError`.
### Proteção
`Object.seal()` cria um objeto "selado", o que significa que recebe um objeto existente e basicamente chama `Object.preventExtensions()` nele, mas também marca todas as suas propriedades existentes como `configurable: false`.
Então, não só você não pode adicionar mais propriedades, mas você também não pode reconfigurar ou apagar quaisquer propriedades existentes (embora você ainda possa modificar seus valores).
### Travamento
`Object.freeze()` cria um objeto congelado, o que significa que é preciso um objeto existente e basicamente chama `objeto.seal()` nele, mas também marca todas as propriedades do tipo "acesso a dados" como writable:false, para que seus valores não possam ser alterados.
Essa abordagem é o maior nível de imutabilidade que você pode alcançar para um objeto em si, pois impede quaisquer mudanças no objeto ou em qualquer uma de suas propriedades diretas (embora, como mencionado acima, o conteúdo de quaisquer outros objetos referenciados não seja afetado).
```js
let immutableObject = Object.freeze({});
```
Congelar um objeto não permite que novas propriedades sejam adicionadas a um objeto e impede que os usuários removam ou modifiquem as propriedades existentes. `Object.freeze()` preserva a enumerabilidade, configurabilidade, gravabilidade e protótipo do objeto. Ele retorna o objeto passado e não cria uma cópia congelada.
## Quais são os prós e os contras da imutabilidade?
### Prós
- Detecção de mudanças mais fácil: A igualdade de objetos pode ser determinada de maneira eficiente e fácil por meio da igualdade referencial. Isso é útil para comparar diferenças de objetos no React e Redux.
- Menos complicado: Programas com objetos imutáveis são menos complicados de se pensar, já que você não precisa se preocupar sobre como um objeto pode evoluir ao longo do tempo.
- Compartilhamento fácil por referências: Uma cópia de um objeto é tão boa quanto outra, então você pode armazenar objetos em cache ou reutilizar o mesmo objeto várias vezes.
- Seguro para threads: Objetos imutáveis podem ser usados com segurança entre threads em um ambiente multi-threaded, já que não há risco de serem modificados em outras threads que estão sendo executadas simultaneamente.
- Menos necessidade de memória: Usando bibliotecas como [Immer](https://immerjs.github.io/immer/) e [Immutable.js](https://immutable-js.com/), objetos são modificados usando compartilhamento estrutural e menos memória é necessária para ter vários objetos com estruturas semelhantes.
- Não há necessidade de cópias defensivas: cópias defensivas não são mais necessárias quando objetos imutáveis são retornados ou passados para funções, uma vez que não há possibilidade de um objeto imutável ser modificado por ela.
### Contras
- Complexo para criar por si mesmo: Implementações ingênuas de estruturas de dados imutáveis e suas operações podem resultar em desempenho extremamente pobre porque novos objetos são criados cada vez. É recomendado o uso de bibliotecas para estruturas de dados imutáveis e operações eficientes que utilizam compartilhamento estrutural.
- Potencial impacto negativo na performance: Alocação (e desalocação) de muitos objetos pequenos ao invés de modificar objetos existentes pode causar um impacto na performance. A complexidade do alocador ou do coletor de lixo geralmente depende do número de objetos no heap.
- Complexidade para estruturas de dados cíclicas: estruturas de dados cíclicas como grafos são difíceis de construir. Se você tiver dois objetos que não podem ser modificados após a inicialização, como você pode fazer com que eles apontem um para o outro?

View File

@ -1,81 +0,0 @@
---
title: 解释可变和不可变对象之间的差异
---
不可变性是函数式编程的一个核心原则,对面向对象的程序也有很多好处。 可变对象是一个可以在创建后修改状态的对象。 不可变对象是一个在创建后无法修改状态的对象。
## JavaScript 中有什么是不可变对象的例子?
在 JavaScript 中,一些内置类型 (数字,字符串) 是不可变的,但自定义对象通常是可变的。
一些内置不可变的 JavaScript 对象是 `Math`, `Date`。
这里有几种方法在普通 JavaScript 对象上添加/模拟不可变性。
### 对象常量属性
通过将`writable: false` 和 `configurable: false`, 你基本上可以创建一个不变值(无法更改, 重新定义或删除) 作为对象属性, 例如:
```js
let myObject = {};
Object.defineProperty(myObject, 'number', {
value: 42,
writable: false,
configurable: false,
});
console.log(myObject.number); // 42
myObject.number = 43;
console.log(myObject.number); // 42
```
### 防止扩展
如果你想阻止一个对象被添加新的属性,但在其他方面不影响该对象的其他属性,可以调用`Object.preventExtensions(...)`
```js
let myObject = {
a: 2,
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
```
在非严格模式下,`b`的创建静默失败了。 在严格模式下,它会抛出一个 `TypeError` 。
### 密封
`Object.seal()`创建一个 "密封 "的对象,这意味着它采用一个现有的对象,并基本上对其调用`Object.preventExtensions()`,但也将其所有现有属性标记为 `configurable: false`。
因此,你不仅不能再添加任何属性,而且也不能重新配置或删除任何现有的属性(尽管你仍然可以修改其值)。
### 冻结
`Object.freeze()`创建一个冻结的对象,这意味着它采用一个现有的对象,并基本上对其调用`Object.seal()`,但它也将所有 "数据访问器 "属性标记为`writable: false` ,所以它们的值不能被改变。
这种方法是你对一个对象本身所能达到的最高级别的不变性,因为它可以防止对该对象或其任何直接属性的任何改变(尽管如上所述,任何被引用的其他对象的内容都不会受到影响)。
```js
let immutableObject = Object.freeze({});
```
冻结对象不允许将新属性添加到对象中,并阻止用户删除或更改现有属性。 `Object.freeze()`保留了对象的可枚举性、可配置性、可写入性和原型。 它返回传递的对象(第一个参数),不会创建一个冻结的副本。
## 不可变性的利弊是什么?
### 优点
- 更容易的变化检测:对象的平等性可以通过一种高效和简单的方式即引用的平等性来确定。 这有助于 React 和 Redux 中比较对象的差异。
- 复杂程度较低:具有不可变对象的方案不那么复杂而难以思考, 因为你不需要担心一个对象可能会随着时间而演变。
- 通过引用轻松共享:一个对象的一个副本和另一个一样好,所以你可以缓存对象或多次重复使用同一个对象。
- 线程安全:在多线程环境中,可以安全地在线程之间使用不可变的对象,因为在其他同时运行的线程中不存在修改这些对象的风险。
- 需要更少的内存:使用库,例如 [Immer](https://immerjs.github.io/immer/) 和 [Immutable.js](https://immutable-js), 对象是使用结构共享进行修改, 具有相似结构的多个对象需要较少内存。
- 不需要防御性拷贝:当不可变的对象从函数中返回或传递给函数时,不再需要防御性拷贝,因为不可变的对象不可能被它所修改。
### 缺点
- 复杂,要自己创建:对不可变的数据结构及其操作的天真实现会导致性能极差,因为每次都要创建新的对象。 建议利用库来建立高效的不可改变的数据结构和运作,从而对结构共享产生影响。
- 潜在的负面性能:分配(和减少分配)许多小对象,而不是修改现有对象,可能会对性能产生影响。 内存分配器或垃圾收集器的复杂性通常取决于堆上对象的数量。
- 循环数据结构的复杂性:像图表这样的循环数据结构难以构建。 如果您有两个在初始化后无法修改的对象,如何让它们指向对方?

View File

@ -1,172 +0,0 @@
---
title: Explain the difference between synchronous and asynchronous functions
---
## TL;DR
Synchronous functions are blocking while asynchronous functions are not. In synchronous functions, statements complete before the next statement is run. As a result, programs containing only synchronous code are evaluated exactly in order of the statements. The execution of the program is paused if one of the statements take a very long time.
```js
function sum(a, b) {
console.log('Inside sum function');
return a + b;
}
const result = sum(2, 3); // The program waits for sum() to complete before assigning the result
console.log('Result: ', result); // Output: 5
// Console output:
// Inside sum function
// Result: 5
```
Asynchronous functions usually accept a callback as a parameter and execution continue on to the next line immediately after the asynchronous function is invoked. The callback is only invoked when the asynchronous operation is complete and the call stack is empty. Heavy duty operations such as loading data from a web server or querying a database should be done asynchronously so that the main thread can continue executing other operations instead of blocking until that long operation to complete (in the case of browsers, the UI will freeze).
```js
function fetchData(callback) {
setTimeout(() => {
const data = { name: 'John', age: 30 };
callback(data); // Calling the callback function with data
}, 2000); // Simulating a 2-second delay
}
console.log('Fetching data...');
fetchData((data) => {
console.log(data); // Output: { name: 'John', age: 30 } (after 2 seconds)
});
console.log('Call made to fetch data'); // Output: This will be printed first
// Console output:
// Fetching data...
// Call made to fetch data
// { name: 'John', age: 30 }
```
---
## Synchronous vs asynchronous functions
In JavaScript, the concepts of synchronous and asynchronous functions are fundamental to understanding how code execution is managed, particularly in the context of handling operations like I/O tasks, API calls, and other time-consuming processes.
## Synchronous functions
Synchronous functions execute in a sequential order, one after the other. Each operation must wait for the previous one to complete before moving on to the next.
- Synchronous code is blocking, meaning the program execution halts until the current operation finishes.
- It follows a strict sequence, executing instructions line by line.
- Synchronous functions are easier to understand and debug since the flow is predictable.
### Synchronous function examples
1. **Reading files synchronously**: When reading a file from the file system using the synchronous readFileSync method from the fs module in Node.js, the program execution is blocked until the entire file is read. This can cause performance issues, especially for large files or when reading multiple files sequentially
```js
const fs = require('fs');
const data = fs.readFileSync('large-file.txt', 'utf8');
console.log(data); // Execution is blocked until the file is read.
console.log('End of the program');
```
2. **Looping over large datasets**: Iterating over a large array or dataset synchronously can freeze the user interface or browser tab until the operation completes, leading to an unresponsive application.
```js
const largeArray = new Array(1_000_000).fill(0);
// Blocks the main thread until the million operations are completed.
const result = largeArray.map((num) => num * 2);
console.log(result);
```
## Asynchronous functions
Asynchronous functions do not block the execution of the program. They allow other operations to continue while waiting for a response or completion of a time-consuming task.
- Asynchronous code is non-blocking, allowing the program to keep running without waiting for a specific operation to finish.
- It enables concurrent execution, improving performance and responsiveness.
- Asynchronous functions are commonly used for tasks like network requests, file I/O, and timers.
### Asynchronous function examples
1. **Network requests**: Making network requests, such as fetching data from an API or sending data to a server, is typically done asynchronously. This allows the application to remain responsive while waiting for the response, preventing the user interface from freezing
```js
console.log('Start of the program'); // This will be printed first as program starts here
fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => {
console.log(data);
/** Process the data without blocking the main thread
* and printed at the end if fetch call succeeds
*/
})
.catch((error) => console.error(error));
console.log('End of program'); // This will be printed next before the fetch callback
```
2. **User input and events**: Handling user input events, such as clicks, key presses, or mouse movements, is inherently asynchronous. The application needs to respond to these events without blocking the main thread, ensuring a smooth user experience.
```js
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
// Handle the click event asynchronously
console.log('Button clicked');
});
```
3. **Timers and Animations**: Timers (`setTimeout()`, `setInterval()`) and animations (e.g., `requestAnimationFrame()`) are asynchronous operations that allow the application to schedule tasks or update animations without blocking the main thread.
```js
setTimeout(() => {
console.log('This message is delayed by 2 seconds');
}, 2000);
const animationId = requestAnimationFrame(updateAnimation);
```
By using asynchronous functions and operations, JavaScript can handle time-consuming tasks without freezing the user interface or blocking the main thread.
It is important to note that **`async` functions do not run on a different thread**. They still run on the main thread. However, it is possible to achieve parallelism in JavaScript by using [Web workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)
## Achieving parallelism in JavaScript via web workers
Web workers allow you to spawn separate background threads that can perform CPU-intensive tasks in parallel with the main thread. These worker threads can communicate with the main thread via message passing, but they do not have direct access to the DOM or other browser APIs.
```js
// main.js
const worker = new Worker('worker.js');
worker.onmessage = function (event) {
console.log('Result from worker:', event.data);
};
worker.postMessage('Start computation');
```
```js
// worker.js
self.onmessage = function (event) {
const result = performHeavyComputation();
self.postMessage(result);
};
function performHeavyComputation() {
// CPU-intensive computation
return 'Computation result';
}
```
In this example, the main thread creates a new web worker and sends it a message to start a computation. The worker performs the heavy computation in parallel with the main thread and sends the result back via `postMessage()`.
## Event loop
The async nature of JavaScript is powered by a JavaScript engine's [event loop](/questions/quiz/what-is-event-loop-what-is-the-difference-between-call-stack-and-task-queue) allowing concurrent operations even though JavaScript is single-threaded. It's an important concept to understand so we highly recommend going through that topic as well.
## Further reading
- [Asynchronous JavaScript](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous)
- [The Basics: synchronous and asynchronous JavaScript](https://www.linkedin.com/pulse/basics-synchronous-asynchronous-javascript-abdulkabir-okeowo)
- [Synchronous and asynchronous programming in JavaScript](https://code.pieces.app/blog/synchronous-and-asynchronous-programming-in-javascript)
- [Web Workers API - MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API)
- [An overview of web workers - Web.dev](https://web.dev/learn/performance/web-worker-overview)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-the-difference-between-synchronous-and-asynchronous-functions",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "high",
"difficulty": "medium"
}

View File

@ -1,7 +0,0 @@
---
title: Explique a diferença entre funções síncronas e assíncronas
---
Funções síncronas são bloqueadoras enquanto funções assíncronas não são. Em funções síncronas, as instruções são concluídas antes que a próxima instrução seja executada. Nesse caso, o programa é avaliado exatamente na ordem das instruções, e a execução do programa é pausada se uma das instruções demorar muito tempo.
Funções assíncronas geralmente aceitam uma função de retorno de chamada como parâmetro e a execução continua na próxima linha imediatamente após a invocação da função assíncrona. A callback só é invocada quando a operação assíncrona é concluída e a pilha de chamadas está vazia. Operações pesadas, como carregar dados de um servidor web ou consultar um banco de dados, devem ser feitas de forma assíncrona para que a thread principal possa continuar executando outras operações em vez de bloquear até que aquela operação longa seja concluída (no caso dos navegadores, a interface do usuário ficará congelada).

View File

@ -1,7 +0,0 @@
---
title: 解释同步函数和异步函数之间的差异
---
同步函数是阻塞的,而异步函数则不是。 在同步函数中,语句在运行下一个语句之前完成。 在这种情况下, 该程序正是按照语句的顺序进行执行,如果其中一个语句需要很长时间,则该程序的执行将暂停。
异步函数通常接受回调作为参数,并在调用异步函数后立即在下一行继续执行。 回调只有在异步操作完成且调用栈为空时才会被调用。 重型操作,例如从网络服务器上加载数据或查询数据库应该异步进行,以便主线程能够继续执行其他操作,而不是等到那个漫长的阻塞操作完成(在浏览器的情况下,界面将冻结)。

View File

@ -1,101 +0,0 @@
---
title: Explain the differences between CommonJS modules and ES modules
---
## TL;DR
In JavaScript, modules are reusable pieces of code that encapsulate functionality, making it easier to manage, maintain, and structure your applications. Modules allow you to break down your code into smaller, manageable parts, each with its own scope.
**CommonJS** is an older module system that was initially designed for server-side JavaScript development with Node.js. It uses the `require()` function to load modules and the `module.exports` or `exports` object to define the exports of a module.
```js
// my-module.js
const value = 42;
module.exports = { value };
// main.js
const myModule = require('./my-module.js');
console.log(myModule.value); // 42
```
**ES Modules** (ECMAScript Modules) are the standardized module system introduced in ES6 (ECMAScript 2015). They use the `import` and `export` statements to handle module dependencies.
```js
// my-module.js
export const value = 42;
// main.js
import { value } from './my-module.js';
console.log(value); // 42
```
**CommonJS vs ES modules**
| Feature | CommonJS | ES modules |
| --- | --- | --- |
| Module Syntax | `require()` for importing `module.exports` for exporting | `import` for importing `export` for exporting |
| Environment | Primarily used in Node.js for server-side development | Designed for both browser and server-side JavaScript (Node.js) |
| Loading | Synchronous loading of modules | Asynchronous loading of modules |
| Structure | Dynamic imports, can be conditionally called | Static imports/exports at the top level |
| File extensions | `.js` (default) | `.mjs` or `.js` (with `type: "module"` in `package.json`) |
| Browser support | Not natively supported in browsers | Natively supported in modern browsers |
| Optimization | Limited optimization due to dynamic nature | Allows for optimizations like tree-shaking due to static structure |
| Compatibility | Widely used in existing Node.js codebases and libraries | Newer standard, but gaining adoption in modern projects |
---
## Modules in Javascript
Modules in JavaScript are a way to organize and encapsulate code into reusable and maintainable units. They allow developers to break down their codebase into smaller, self-contained pieces, promoting code reuse, separation of concerns, and better organization. There are two main module systems in JavaScript: CommonJS and ES modules.
### CommonJS
CommonJS is an older module system that was initially designed for server-side JavaScript development with Node.js. It uses the require function to load modules and the `module.exports` or `exports` object to define the exports of a module.
- **Syntax**: Modules are included using `require()` and exported using `module.exports`.
- **Environment**: Primarily used in `Node.js`.
- **Execution**: Modules are loaded synchronously.
- Modules are loaded dynamically at runtime.
```js
// my-module.js
const value = 42;
module.exports = { value };
// main.js
const myModule = require('./my-module.js');
console.log(myModule.value); // 42
```
### ES Modules
ES Modules (ECMAScript Modules) are the standardized module system introduced in ES6 (ECMAScript 2015). They use the `import` and `export` statements to handle module dependencies.
- **Syntax**: Modules are imported using `import` and exported using `export`.
- **Environment**: Can be used in both browser environments and Node.js (with certain configurations).
- **Execution**: Modules are loaded asynchronously.
- **Support**: Introduced in ES2015, now widely supported in modern browsers and Node.js.
- Modules are loaded statically at compile-time.
- Enables better performance due to static analysis and tree-shaking.
```js
// my-module.js
export const value = 42;
// main.js
import { value } from './my-module.js';
console.log(value); // 42
```
## Summary
While CommonJS was the default module system in Node.js initially, ES modules are now the recommended approach for new projects, as they provide better tooling, performance, and ecosystem compatibility. However, CommonJS modules are still widely used in existing code bases and libraries especially for legacy dependencies.
## Further reading
- [JavaScript modules - MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
- [CommonJS vs ES Modules: the shift from require to import](https://nikolasbarwicki.com/articles/commonjs-vs-es-modules-the-shift-from-require-to-import/)
- [Modules, introduction - javascript.info](https://javascript.info/modules-intro)
- [Modules - Eloquent Javascript](https://eloquentjavascript.net/10_modules.html)
- [CommonJS vs. ES modules in Node.js](https://blog.logrocket.com/commonjs-vs-es-modules-node-js/)
- [Understanding CommonJS vs. ES Modules in JavaScript](https://www.syncfusion.com/blogs/post/js-commonjs-vs-es-modules)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-the-differences-between-commonjs-modules-and-es-modules",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "mid",
"difficulty": "hard"
}

View File

@ -1,113 +0,0 @@
---
title: Explain the differences on the usage of `foo` between `function foo() {}` and `var foo = function() {}`
---
## TL;DR
`function foo() {}` a function declaration while the `var foo = function() {}` is a function expression. The key difference is that function declarations have its body hoisted but the bodies of function expressions are not (they have the same hoisting behavior as `var`-declared variables).
If you try to invoke a function expression before it is declared, you will get an `Uncaught TypeError: XXX is not a function` error.
Function declarations can be called in the enclosing scope even before they are declared.
```js
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
```
Function expressions if called before they are declared will result in an error.
```js
foo(); // Uncaught TypeError: foo is not a function
var foo = function () {
console.log('FOOOOO');
};
```
Another key difference is in the scope of the function name. Function expressions can be named by defining it after the `function` and before the parenthesis. However when using named function expressions, the function name is only accessible within the function itself. Trying to access it outside will result in an error or `undefined`.
```js
const myFunc = function namedFunc() {
console.log(namedFunc); // Works
};
console.log(namedFunc); // undefined
```
**Note**: The examples uses `var` due to legacy reasons. Function expressions can be defined using `let` and `const` and the key difference is in the hoisting behavior of those keywords.
---
## Function declarations
A function declaration is a statement that defines a function with a name. It is typically used to declare a function that can be called multiple times throughout the enclosing scope.
```js
function foo() {
console.log('FOOOOO');
}
```
## Function expressions
A function expression is an expression that defines a function and assigns it to a variable. It is often used when a function is needed only once or in a specific context.
```js
var foo = function () {
console.log('FOOOOO');
};
```
**Note**: The examples uses `var` due to legacy reasons. Function expressions can be defined using `let` and `const` and the key difference is in the hoisting behavior of those keywords.
## Key differences
### Hoisting
The key difference is that function declarations have its body hoisted but the bodies of function expressions are not (they have the same hoisting behavior as `var`-declared variables). For more explanation on hoisting, refer to the quiz question on [hoisting](/questions/quiz/explain-hoisting). If you try to invoke a function expression before it is defined, you will get an `Uncaught TypeError: XXX is not a function` error.
Function declarations:
```js
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
```
Function expressions:
```js
foo(); // Uncaught TypeError: foo is not a function
var foo = function () {
console.log('FOOOOO');
};
```
### Name scope
Function expressions can be named by defining it after the `function` and before the parenthesis. However when using named function expressions, the function name is only accessible within the function itself. Trying to access it outside will result in `undefined` and calling it will result in an error.
```js
const myFunc = function namedFunc() {
console.log(namedFunc); // Works
};
console.log(namedFunc); // undefined
```
## When to use each
- Function declarations:
- When you want to create a function on the global scope and make it available throughout the enclosing scope.
- If a function is reusable and needs to be called multiple times.
- Function expressions:
- If a function is only needed once or in a specific context.
- Use to limit the function availability to subsequent code and keep the enclosing scope clean.
In general, it's preferable to use function declarations to avoid the mental overhead of determining if a function can be called. The practical usages of function expressions is quite rare.
## Further reading
- [Function declaration | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function)
- [Function expression | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/function)

View File

@ -1,11 +0,0 @@
{
"slug": "explain-the-differences-on-the-usage-of-foo-between-function-foo-and-var-foo-function",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "mid",
"difficulty": "medium"
}

View File

@ -1,23 +0,0 @@
---
title: Explique as diferenças no uso de `foo` entre `function foo() {}` e `var foo = function() {}`
---
O primeiro é uma declaração de funções, enquanto o segundo é uma expressão de funções. A diferença chave é que as declarações de funções tem seu corpo hoisted, mas os corpos das expressões de função não são (elas têm o mesmo comportamento hoisting que as variáveis). Para obter mais explicações sobre o hoisting, consulte a pergunta sobre [hoisting](/questions/quiz/explain-hoisting). Se você tentar invocar uma expressão de função antes de ela ser definida, você receberá um erro `Uncaught TypeError: XXX não é um erro de função`.
## Declaração de Função
```js
foo(); // 'FOOOO'
function foo() {
console.log('FOOOOO');
}
```
## Expressão de Função
```js
foo(); // Uncaught TypeError: foo não é uma função
var foo = function () {
console.log('FOOOOO');
};
```

View File

@ -1,23 +0,0 @@
---
title: 解释`function foo() {}` 和 `var foo = function() {}` 之间在`foo` 使用方法上的差异
---
前者是一个函数声明,而后者是一个函数表达式。 关键的区别是,函数声明会使它的主体被提升,但函数表达式的主体没有被提升(它们有和变量一样的提升行为)。 想要了解更多关于提升的解释,请参阅 [提升](/questions/quiz/explanin-hoisting)。 如果你试图在定义之前调用函数表达式,你将会得到一个 `Uncaught TypeError: XXX is not a function` 。
## 函数声明
```js
foo(); // 'FOOOOO'
function foo() {
console.log('FOOOOO');
}
```
## 函数表达式
```js
foo(); // Uncaught TypeError: foo is not a function
var foo = function () {
console.log('FOOOOO');
};
```

View File

@ -1,5 +0,0 @@
---
title: Explain the same-origin policy with regards to JavaScript
---
The same-origin policy prevents JavaScript from making requests across domain boundaries. An origin is defined as a combination of URI scheme, hostname, and port number. This policy prevents a malicious script on one page from obtaining access to sensitive data on another web page through that page's Document Object Model.

View File

@ -1,11 +0,0 @@
{
"slug": "explain-the-same-origin-policy-with-regards-to-javascript",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript", "network"],
"importance": "low",
"difficulty": "hard"
}

View File

@ -1,5 +0,0 @@
---
title: Explique a política de mesma origem em relação ao JavaScript
---
A política de mesma origem impede o JavaScript de fazer solicitações além dos limites de domínio. Uma origem é definida como uma combinação de esquema URI, nome do host e número da porta. Essa política impede que um script malicioso em uma página obtenha acesso a dados sensíveis em outra página da web por meio do Document Object Model dessa página.

View File

@ -1,5 +0,0 @@
---
title: 解释与JavaScript有关的同源策略。
---
同源策略阻止 JavaScript 跨域发出请求。 一个源被定义为 URI 协议、主机名和端口号的组合。 这项政策防止一个页面上的恶意脚本通过该页面的文档对象模型访问另一个网页上的敏感数据。

View File

@ -1,19 +0,0 @@
---
title: Explain what a single page app is and how to make one SEO-friendly
---
Web developers these days refer to the products they build as web apps, rather than websites. While there is no strict difference between the two terms, web apps tend to be highly interactive and dynamic, allowing the user to perform actions and receive a response to their action. Traditionally, the browser receives HTML from the server and renders it. When the user navigates to another URL, a full-page refresh is required and the server sends fresh new HTML to the new page. This is called server-side rendering.
However, in modern SPAs, client-side rendering is used instead. The browser loads the initial page from the server, along with the scripts (frameworks, libraries, app code) and stylesheets required for the whole app. When the user navigates to other pages, a page refresh is not triggered. The URL of the page is updated via the [HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API). New data required for the new page, usually in JSON format, is retrieved by the browser via [AJAX](https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started) requests to the server. The SPA then dynamically updates the page with the data via JavaScript, which it has already downloaded in the initial page load. This model is similar to how native mobile apps work.
## Pros
- The app feels more responsive and users do not see the flash between page navigations due to full-page refreshes.
- Fewer HTTP requests are made to the server, as the same assets do not have to be downloaded again for each page load.
- Clear separation of the concerns between the client and the server; you can easily build new clients for different platforms (e.g. mobile, chatbots, smart watches) without having to modify the server code. You can also modify the technology stack on the client and server independently, as long as the API contract is not broken.
## Cons
- Heavier initial page load due to the loading of framework, app code, and assets required for multiple pages.
- There's an additional step to be done on your server which is to configure it to route all requests to a single entry point and allow client-side routing to take over from there.
- SPAs are reliant on JavaScript to render content, but not all search engines execute JavaScript during crawling, and they may see empty content on your page. This inadvertently hurts the Search Engine Optimization (SEO) of your app. However, most of the time, when you are building apps, SEO is not the most important factor, as not all the content needs to be indexable by search engines. To overcome this, you can either server-side render your app or use services such as [Prerender](https://prerender.io/) to "render your javascript in a browser, save the static HTML, and return that to the crawlers".

View File

@ -1,11 +0,0 @@
{
"slug": "explain-what-a-single-page-app-is-and-how-to-make-one-seo-friendly",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "mid",
"difficulty": "hard"
}

View File

@ -1,19 +0,0 @@
---
title: Explique o que é um aplicativo de página única e como torná-lo amigável para SEO
---
Os desenvolvedores web atualmente se referem aos produtos que constroem como aplicativos web, em vez de sites. Embora não haja uma diferença estrita entre os dois termos, os aplicativos web tendem a ser altamente interativos e dinâmicos, permitindo que o usuário execute ações e receba uma resposta para sua ação. Tradicionalmente, o navegador recebe o HTML do servidor e o renderiza. Quando o usuário navegar para outra URL, é necessária uma atualização de página inteira e o servidor envia novo HTML para a nova página. Isso é chamado de renderização no lado do servidor.
No entanto, em SPAs modernas, é usado o rendering no lado do cliente (client-side rendering) em vez disso. O navegador carrega a página inicial do servidor, juntamente com os scripts (frameworks, bibliotecas, código do aplicativo) e folhas de estilo necessárias para todo o aplicativo. Quando o usuário navega para outras páginas, uma atualização de página não é acionada. A URL da página é atualizada através da [API Histórico HTML5](https://developer.mozilla.org/en-US/docs/Web/API/History_API). Novos dados necessários para a nova página, geralmente no formato JSON, são recuperados pelo navegador via [AJAX](https://developer.mozilla.org/en-US/docs/AJAX/Getting_Started) pedidos ao servidor. O SPA, em seguida, atualiza dinamicamente a página com dados via JavaScript, que já foi baixado na carga inicial da página. Esse modelo é semelhante a como os aplicativos nativos dos dispositivos móveis funcionam.
## Prós
- O aplicativo parece mais responsivo e os usuários não veem o flash entre as navegações de página devido às atualizações completas da página.
- São feitas menos solicitações HTTP ao servidor, pois os mesmos recursos não precisam ser baixados novamente a cada carga de página.
- Há uma clara separação das responsabilidades entre o cliente e o servidor, permitindo a fácil construção de novos clientes para diferentes plataformas (por exemplo, dispositivos móveis, chatbots, relógios inteligentes) sem precisar modificar o código do servidor. Você também pode modificar a pilha de tecnologia no cliente e no servidor independentemente, desde que o contrato da API não seja quebrado.
## Contras
- Há uma carga inicial de página mais pesada devido ao carregamento do framework, código do aplicativo e recursos necessários para várias páginas.
- Há uma etapa adicional a ser feita no seu servidor, que é configurá-lo para rotear todas as solicitações para um único ponto de entrada e permitir que o roteamento do lado do cliente assuma a partir daí.
- As SPAs dependem do JavaScript para renderizar conteúdo, mas nem todos os mecanismos de pesquisa executam JavaScript durante a rastreamento e podem ver conteúdo vazio em sua página. Isso prejudica inadvertidamente a otimização de mecanismos de pesquisa (SEO) do seu aplicativo. No entanto, na maioria das vezes, ao construir aplicativos, o SEO não é o fator mais importante, pois nem todo o conteúdo precisa ser indexável pelos mecanismos de pesquisa. Para contornar esse problema, você pode renderizar seu aplicativo no servidor ou usar serviços como [Prerender](https://prerender.io/) para "renderizar seu JavaScript em um navegador, salvar o HTML estático e retorná-lo aos crawlers".

View File

@ -1,19 +0,0 @@
---
title: 解释一个单页应用程序是什么以及如何优化SEO
---
当代的网络开发者指出他们构建的产品是 Web 应用,而不是网站。 虽然这两个词之间没有严格区别,但 Web 应用往往具有高度的互动性和动态, 允许用户执行操作并收到对其操作的响应。 通常情况下,浏览器从服务器接收 HTML 并渲染它。 当用户导航到另一个 URL 时,需要全页刷新,服务器将新的 HTML 发送到新页面。 这被称为服务器端渲染。
然而,在现代 SPA 中,则使用客户端渲染。 浏览器从服务器加载初始页面,以及整个应用程序所需的脚本(框架、库、应用代码) 和样式表。 当用户导航到其他页面时,不会触发页面刷新。 页面的 URL 通过[HTML5 History API](https://developer.mozilla.org/en-US/docs/Web/API/History_API)更新。 新页面所需的新数据,通常使用 JSON 格式,由浏览器通过 [AJAX](https://developer.mozilla.org/en-US/docs/AJAX/Getting_Start) 向服务器检索. SPA 然后通过 JavaScript 动态地更新页面数据,它已经在初始页面加载中下载好了。 此模型类似于本地移动应用的工作方式。
## 优点
- 由于全页刷新,应用感觉更加敏捷,用户没有看到页面导航之间的闪烁。
- 服务器收到的 HTTP 请求较少,因为同一个资源不必在每个页面加载时再次下载。
- 客户端和服务器之间的关注点明确分离;你可以很容易地为不同的平台(如手机、聊天机器人、智能手表)建立新的客户端,而不必修改服务器代码。 只要 API 约定未被损坏,您也可以独立修改客户端和服务器上的技术堆栈。
## 缺点
- 由于加载框架、应用程序代码和多个页面所需的资产,初始页面负载较重。
- 在您的服务器上还有一个步骤要做,即配置它来将所有请求路由到一个单一的入口点,并允许客户端路由从那里接管。
- SPA 依赖 JavaScript 来呈现内容,但并非所有的搜索引擎在抓取过程中都会执行 JavaScript它们可能会在你的页面上看到空的内容。 这无意中伤害了您的应用程序的 SEO搜索引擎优化。 然而在大多数情况下当你正在建造应用软件时SEO 并不是最重要的因素, 因为并非所有内容都需要通过搜索引擎索引。 为了克服这个问题,你可以在服务器端渲染你的应用程序,或者使用[Plerender](https://prerender.io/)等服务来 "在浏览器中渲染你的 JavaScript保存静态 HTML并将其返回给爬虫"。

View File

@ -1,17 +0,0 @@
---
title: "Explain why the following doesn't work as an IIFE: `function foo(){ }();`. What needs to be changed to properly make it an IIFE?"
---
IIFE stands for Immediately Invoked Function Expressions. The JavaScript parser reads `function foo(){ }();` as `function foo(){ }` and `();`, where the former is a _function declaration_ and the latter (a pair of parentheses) is an attempt at calling a function but there is no name specified, hence it throws `Uncaught SyntaxError: Unexpected token )`.
Here are two ways to fix it that involves adding more parentheses: `(function foo(){ })()` and `(function foo(){ }())`. Statements that begin with `function` are considered to be _function declarations_; by wrapping this function within `()`, it becomes a _function expression_ which can then be executed with the subsequent `()`. These functions are not exposed in the global scope and you can even omit its name if you do not need to reference itself within the body.
You might also use `void` operator: `void function foo(){ }();`. Unfortunately, there is one issue with such approach. The evaluation of given expression is always `undefined`, so if your IIFE function returns anything, you can't use it. An example:
```js
const foo = void (function bar() {
return 'foo';
})();
console.log(foo); // undefined
```

View File

@ -1,11 +0,0 @@
{
"slug": "explain-why-the-following-doesnt-work-as-an-iife-function-foo--what-needs-to-be-changed-to-properly-make-it-an-iife",
"languages": [],
"companies": [],
"premium": false,
"duration": 5,
"published": true,
"topics": ["javascript"],
"importance": "low",
"difficulty": "hard"
}

View File

@ -1,17 +0,0 @@
---
title: 'Explique porque o seguinte não funciona como um IIFE: `function foo(){ }();`. O que precisa ser alterado para torná-lo corretamente um IIFE?'
---
IIFE significa expressões de função imediatamente invocadas. O interpretador JavaScript lê `function foo(){ }();` como `function foo(){ }` e `();`, onde o primeiro é uma declaração de função e o último (um par de parênteses) é uma tentativa de chamar uma função, mas não há nome especificado, portanto, ele retorna `Uncaught SyntaxError: Unexpected token )`.
Aqui estão duas maneiras de corrigir que envolve a adição de mais parênteses: `(function foo(){ })()` e `(function foo(){ }())`. Declarações que começam com `function` são consideradas como _function declarations_ ao envolver essa função dentro de `()`, ela se torna uma _function expression_ que pode ser executada com o `()` subsequente. Essas funções não são expostas no escopo global e você pode até omitir o nome delas se não precisar fazer referência a si mesmas dentro do corpo.
Você também pode usar o operador `void`: `void function foo(){ }();`. Infelizmente, há um problema com essa abordagem. A avaliação da expressão fornecida é sempre undefined, então, se sua função IIFE retornar algo, você não poderá usá-la. Um exemplo:
```js
const foo = void (function bar() {
return 'foo';
})();
console.log(foo); // indefinido
```

View File

@ -1,17 +0,0 @@
---
title: '解释这为什么不能以IIFE工作: `function foo(){ }();`. 为了使它成为一个IIFE需要作出哪些改变'
---
IIFE 是 Immediately Invoked Function Expressions 的缩写,即立即调用函数表达式。 JavaScript 解析器读取`function foo(){ }();` 作为 `function foo(){ }` 和 `(); `, 如果前者是一个 _函数声明_, 而后者是一对括号, 则试图调用函数, 但没有指定名称, 因此,它抛出`Uncaught SyntaxError: Unexpected token )`。
这里有两种方法修复它,涉及添加更多括号:`(function foo(){ })()` 和 `(function foo(){ }())` 以 `function` 开头的语句被认为是*函数声明*;通过将这个函数包裹在"() "中,它成为一个*函数表达式*,然后可以用后面的`()`执行。 这些函数不会在全局范围内暴露,如果你不需要在代码里提及,你甚至可以省略它的名称。
您也可以使用 `void` 操作符:`void function foo(){ }();`. 不幸的是,这种做法有一个问题。 对给定表达式的执行结果总是\`undefined',所以如果你的 IIFE 函数返回任何东西,你就不能使用它。 举个例子:
```js
const foo = void (function bar() {
return 'foo';
})();
console.log(foo); // undefined
```

Some files were not shown because too many files have changed in this diff Show More