Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Rest parameters and spread operator
# Parâmetros _rest_ e operador _spread_

Many JavaScript built-in functions support an arbitrary number of arguments.
Várias funções embutidas no JavaScript suportam um número arbitrário de argumentos.

For instance:
Por exemplo:

- `Math.max(arg1, arg2, ..., argN)` -- returns the greatest of the arguments.
- `Object.assign(dest, src1, ..., srcN)` -- copies properties from `src1..N` into `dest`.
- ...and so on.
- `Math.max(arg1, arg2, ..., argN)` -- retorna o maior dos argumentos.
- `Object.assign(dest, src1, ..., srcN)` -- copia propriedades de `src1..N` para `dest`.
- ...e assim por diante.

In this chapter we'll learn how to do the same. And, more importantly, how to feel comfortable working with such functions and arrays.
Neste capítulo vamos aprender a fazer o mesmo e, o mais importante, se sentindo confortável trabalhando com tais funções e listas (_arrays_).

## Rest parameters `...`
## Parâmetros _rest_ `...`

A function can be called with any number of arguments, no matter how it is defined.
Uma função pode ser chamada com qualquer número de argumentos, não importa a sua definição.

Like here:
Como por exemplo:
```js run
function sum(a, b) {
return a + b;
Expand All @@ -23,14 +23,14 @@ function sum(a, b) {
alert( sum(1, 2, 3, 4, 5) );
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted.
Não haverão erros por "uso excessivo" de argumentos, mas é claro que somente os dois primeiros valores serão levados em consideração no resultado.

The rest parameters can be mentioned in a function definition with three dots `...`. They literally mean "gather the remaining parameters into an array".
Os parâmetros _rest_, podem ser declarados na definição da função com três pontos `...`. Eles literalmente significam "reúna os parâmetros restantes em uma lista (_array_)".

For instance, to gather all arguments into array `args`:
Por exemplo, para reunir todos os argumentos em um _array_ `args`:

```js run
function sumAll(...args) { // args is the name for the array
function sumAll(...args) { // args é o nome do 'array'
let sum = 0;

for (let arg of args) sum += arg;
Expand All @@ -43,15 +43,15 @@ alert( sumAll(1, 2) ); // 3
alert( sumAll(1, 2, 3) ); // 6
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

We can choose to get the first parameters as variables, and gather only the rest.
Nós podemos escolher receber os primeiros parâmetros como variáveis, e reunir os restantes.

Here the first two arguments go into variables and the rest go into `titles` array:
Abaixo os primeiros dois argumentos vão para variáveis, e os restantes para o _array_ `titles`:

```js run
function showName(firstName, lastName, ...titles) {
alert( firstName + ' ' + lastName ); // Julius Caesar

// the rest go into titles array
// o restante vai para o array titles
// i.e. titles = ["Consul", "Imperator"]
alert( titles[0] ); // Consul
alert( titles[1] ); // Imperator
Expand All @@ -61,55 +61,55 @@ function showName(firstName, lastName, ...titles) {
showName("Julius", "Caesar", "Consul", "Imperator");
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

````warn header="The rest parameters must be at the end"
The rest parameters gather all remaining arguments, so the following does not make sense and causes an error:
````warn header="Os parâmetros rest devem estar no final"
Os parâmetros _rest_ reúnem todos os argumentos restantes, então o exemplo seguinte não faz sentido e causa um erro:

```js
function f(arg1, ...rest, arg2) { // arg2 after ...rest ?!
// error
function f(arg1, ...rest, arg2) { // arg2 depois de ...rest ?!
// erro
}
```

The `...rest` must always be last.
O `...rest` deve estar sempre no final.
````

## The "arguments" variable
## A variável "arguments"

There is also a special array-like object named `arguments` that contains all arguments by their index.
Há também, um tipo especial de objeto com caracteristicas de listas (_array-like_, ou lista genérica), chamado de arguments que contém todos os argumentos segundo a ordem dos seus índices.

For instance:
Por exemplo:

```js run
function showName() {
alert( arguments.length );
alert( arguments[0] );
alert( arguments[1] );

// it's iterable
// é iterável
// for(let arg of arguments) alert(arg);
}

// shows: 2, Julius, Caesar
// exibe: 2, Julius, Caesar
showName("Julius", "Caesar");

// shows: 1, Ilya, undefined (no second argument)
// exibe: 1, Ilya, undefined (não possui um segundo argumento)
showName("Ilya");
```

In old times, rest parameters did not exist in the language, and using `arguments` was the only way to get all arguments of the function, no matter their total number.
Antigamente, parâmetros _rest_ não existiam na linguagem, portanto usar `arguments` era a única forma de receber todos os argumentos da função, não importando o total dos seus argumentos.

And it still works, we can use it today.
E isso ainda funciona atualmente.

But the downside is that although `arguments` is both array-like and iterable, it's not an array. It does not support array methods, so we can't call `arguments.map(...)` for example.
Mas a desvantagem é que, apesar do `arguments` ter algumas caracteristicas de _arrays_ e de ser iterável, não é um _array_ de fato. Ele não suporta métodos de _arrays_, por exemplo, não podemos chamar `arguments.map(...)`.

Also, it always contains all arguments. We can't capture them partially, like we did with rest parameters.
E além disso, sempre contém todos os argumentos. Não podemos os obter parcialmente, como o fizemos com parâmetros _rest_.

So when we need these features, then rest parameters are preferred.
Então, quando precisamos dessas funcionalidades, os parâmetros _rest_ são a preferência.

````smart header="Arrow functions do not have `\"arguments\"`"
If we access the `arguments` object from an arrow function, it takes them from the outer "normal" function.
````smart header="Funções arrow não possuem `\"arguments\"`"
Se tentarmos acessar o objeto `arguments` de dentro de uma função _arrow_, ele os recebe da função "normal" externa.

Here's an example:
Aqui está um exemplo:

```js run
function f() {
Expand All @@ -121,23 +121,23 @@ f(1); // 1
```
````

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

  • The code above seems to contain an error conflict.
    So, in such situations would you check the English article (there is a link here) for ways to resolve the conflict?
    From the text there, you might know how the Portuguese page would look.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't get this "error conflicts" at all, sorry. Can you explain me better what you mean by that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure Luiz, would you please simply copy and paste the code from the English site here The “arguments” variable? (Just above "Spread operator")

Please, remove all code inside, so that the strange characters might disappear, such as:

```js run (please leave there)
 (>>> insert the code here)
``` (please leave there)

(for all cases where conflicts exist, check the English site and copy/paste all needed, including over the strange characters to remove them)
Thanks.

As we remember, arrow functions don't have their own `this`. Now we know they don't have the special `arguments` object either.
Como nos lembramos, funções _arrow_ não possuem o seu próprio `this`. Agora, sabemos que elas também não possuem o especial `arguments`.

## Spread operator [#spread-operator]
## Operador _spread_ [_spread-operator_]

We've just seen how to get an array from the list of parameters.
Acabamos de ver como obter um _array_ de uma lista simples de parâmetros (apenas lista em sequência, não _array_).

But sometimes we need to do exactly the reverse.
Mas às vezes precisamos fazer exatamente o oposto.

For instance, there's a built-in function [Math.max](mdn:js/Math/max) that returns the greatest number from a list:
Por exemplo, existe uma função embutida [Math.max](mdn:js/Math/max) que retorna o maior número de uma lista simples (não _array_):

```js run
alert( Math.max(3, 5, 1) ); // 5
```

Now let's say we have an array `[3, 5, 1]`. How do we call `Math.max` with it?
Agora vamos dizer que temos um _array_ `[3, 5, 1]`. Como podemos fazer para chamar `Math.max` com ele?

Passing it "as is" won't work, because `Math.max` expects a list of numeric arguments, not a single array:
Passar o _array_ "como ele é" não irá funcionar porque, `Math.max` espera uma lista simples de argumentos numéricos, não num todo num _array_.

```js run
let arr = [3, 5, 1];
Expand All @@ -147,21 +147,21 @@ alert( Math.max(arr) ); // NaN
*/!*
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

  • The code above seems to contain an error conflict.
    (In doubt, would you check the English website article (link here)?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Please, check Spread operator - 2nd code block:
    The alert is missing.
    Simply copy/paste, as in the example above.

And surely we can't manually list items in the code `Math.max(arr[0], arr[1], arr[2])`, because we may be unsure how many there are. As our script executes, there could be a lot, or there could be none. And that would get ugly.
E certamente, não podemos listar os itens manualmente no código `Math.max(arr[0], arr[1], arr[2])` porque podemos não a ter certeza de quantos argumentos são. Conforme nosso script é executado, podem haver muitos parâmetros ou pode não haver nenhum. E isso ficaria muito feio.

*Spread operator* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite.
O *operador spread* vem para nos salvar! Ele é bem similar ao parâmetro _rest_, também usando `...`, mas faz o contrário.

When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
Quando `...arr` é usado em uma chamada de função, ele "expande" um objeto iterável `arr` em uma lista simples de argumentos.

For `Math.max`:
Para `Math.max`:

```js run
let arr = [3, 5, 1];

alert( Math.max(...arr) ); // 5 (spread turns array into a list of arguments)
alert( Math.max(...arr) ); // 5 (spread transforma um array em uma lista de argumentos)
```

We also can pass multiple iterables this way:
Também podemos passar múltiplos iteráveis da seguinte forma:

```js run
let arr1 = [1, -2, 3, 4];
Expand All @@ -170,8 +170,7 @@ let arr2 = [8, 3, -8, 1];
alert( Math.max(...arr1, ...arr2) ); // 8
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

  • The code above seems to contain an error conflict.
    (Would you check the English website article (link above)?)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • The second array (arr2) is missing:
    Please, check Spread operator - 4th code block.

We can even combine the spread operator with normal values:

Podemos até combinar o operador spread com valores normais:

```js run
let arr1 = [1, -2, 3, 4];
Expand All @@ -180,7 +179,7 @@ let arr2 = [8, 3, -8, 1];
alert( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

The code above seems to contain an error conflict.
(Would you check the English website article (link above)?)

Copy link
Author

@luizbaldi luizbaldi Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't what you mean by "error conflict". The line 179 looks exactly like the original one on the english version, as we can see here. Can you explain to me what exactly should I do here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Please, check Spread operator - 5th code block:
    The second array (arr2) is missing

Also, the spread operator can be used to merge arrays:
Além disso, o operador spread também pode ser usado para juntar valores individuais de _arrays_:

```js run
let arr = [3, 5, 1];
Expand All @@ -190,56 +189,55 @@ let arr2 = [8, 9, 15];
let merged = [0, ...arr, 2, ...arr2];
*/!*

alert(merged); // 0,3,5,1,2,8,9,15 (0, then arr, then 2, then arr2)
alert(merged); // 0,3,5,1,2,8,9,15 (0, depois arr, depois 2, depois arr2)
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

The code above seems to contain an error conflict.
(Would you check the English website article (link above)?)

Copy link
Author

@luizbaldi luizbaldi Nov 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't what you mean by "error conflict". The line 192 looks exactly like the original one on the english version, as we can see here. Can you explain to me what exactly should I do here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Please, check Spread operator - 6th code block:
    The second array (arr2) is missing
    And also formatting characters

In the examples above we used an array to demonstrate the spread operator, but any iterable will do.
Nos exemplos acima usamos um _array_ para demonstrar o operador _spread_, mas qualquer iterável também funcionaria.

For instance, here we use the spread operator to turn the string into array of characters:
Por exemplo, aqui usamos o operador _spread_ para transformar uma string em um _array_ de caracteres:

```js run
let str = "Hello";
let str = "Olá";

alert( [...str] ); // H,e,l,l,o
alert( [...str] ); // O,l,á
```

The spread operator internally uses iterators to gather elements, the same way as `for..of` does.
Internamente, o operador _spread_ usa iteradores (_iterators_) para reunir elementos, da mesma forma como `for..of` faz.

So, for a string, `for..of` returns characters and `...str` becomes `"H","e","l","l","o"`. The list of characters is passed to array initializer `[...str]`.
Então, para uma string, `for..of` retorna caracteres, e `...str` se torna `"O","l","á"`. A lista de caracteres é passada para o inicializador do _array_ `[...str]`

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please,

  • "... retorna caracteres, e ...str se torna em "O","l","á"."
    (but do not format in bold)

For this particular task we could also use `Array.from`, because it converts an iterable (like a string) into an array:
Para essa tarefa em particular nós também poderíamos usar `Array.from`, porque ele converte um iterável (como uma string) em um _array_.

```js run
let str = "Hello";
let str = "Olá";

// Array.from converts an iterable into an array
alert( Array.from(str) ); // H,e,l,l,o
// Array.from converte um interável em um _array_
alert( Array.from(str) ); // O,l,á
```

The result is the same as `[...str]`.

But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
O resultado é o mesmo que `...[str]`.

- `Array.from` operates on both array-likes and iterables.
- The spread operator operates only on iterables.
Mas há uma diferença sútil entre `Array.from(obj)` e `[...obj]`:

So, for the task of turning something into an array, `Array.from` tends to be more universal.
- `Array.from` opera tanto em listas-genéricas (_array-likes_) como em iteráveis.
- O operador _spread_ opera somente em iteráveis.

Então, para a tarefa de transformar algo em um _array_, `Array.from` tende a ser uma solução mais universal.

## Summary
## Sumário

When we see `"..."` in the code, it is either rest parameters or the spread operator.
Quando nos depararmos com `"..."` no código, estamos falando de parâmetros _rest_ ou do operador _spread_.

There's an easy way to distinguish between them:
Existe uma forma fácil para distinguir entre eles:

- When `...` is at the end of function parameters, it's "rest parameters" and gathers the rest of the list of arguments into an array.
- When `...` occurs in a function call or alike, it's called a "spread operator" and expands an array into a list.
- Quando `...` está no final dos parâmetros da função, é "parâmetros _rest_" e reune o restante da lista de argumentos em um _array_.
- Quando `...` ocorre em uma chamada de função ou similar, é chamado de "operador _spread_" e expande um _array_ em uma lista.

Use patterns:
Padrões de uso:

- Rest parameters are used to create functions that accept any number of arguments.
- The spread operator is used to pass an array to functions that normally require a list of many arguments.
- Operadores _rest_ são usados para criar funções que aceitem qualquer número de argumentos.
- O operador _spread_ é usado para passar um _array_ em funções que normalmente requerem uma lista de muitos argumentos.

Together they help to travel between a list and an array of parameters with ease.
Juntos, eles nos ajudam a efetuar a transição entre uma lista e um _array_ de parâmetros com facilidade.

All arguments of a function call are also available in "old-style" `arguments`: array-like iterable object.
Todos os argumentos de uma chamada de função também estão disponíveis na "moda antiga" `arguments`: objeto iterável do tipo lista-genérica (_array-like_).