Skip to content
Merged
Changes from 1 commit
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
Next Next commit
Translation of rest-parameters-spread-operator articule
  • Loading branch information
gndelia committed Oct 30, 2019
commit e9fbd56b2accffc4718d5281e338135f57148a4c
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
# Rest parameters and spread operator
# Parámetros Rest y operador Spread

Many JavaScript built-in functions support an arbitrary number of arguments.
Muchas funciones nativas de JavaScript soportan un número arbitrario de argumentos.

For instance:
Por ejemplo:

- `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 el argumento más grande.
- `Object.assign(dest, src1, ..., srcN)` -- copia las propiedades de `src1..N` en `dest`.
- ...y otros más

In this chapter we'll learn how to do the same. And, more importantly, how to feel comfortable working with such functions and arrays.
En este capítulo aprenderemos como hacer lo mismo. Y, además, como trabajar cómodamente con dichas funciones y arrays.

## Rest parameters `...`
## Parámetros Rest `...`

A function can be called with any number of arguments, no matter how it is defined.
Una función puede ser llamada con cualquier número de argumentos sin importar como sea definida.

Like here:
Por ejemplo::
```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) );
```

There will be no error because of "excessive" arguments. But of course in the result only the first two will be counted.
Aqui no habrá ningún error por "exceso" de argumentos. Pero, por supuesto, en el resultado solo los dos primeros serán tomados en cuenta.

The rest parameters can be mentioned in a function definition with three dots `...`. They literally mean "gather the remaining parameters into an array".
El resto de los parámetros pueden ser referenciados en la definición de una función con 3 puntos `...` seguidos por el nombre del array que los contendrá. Literalmente significan "Reunir los parámetros restantes en un array".

For instance, to gather all arguments into array `args`:
Por ejemplo, para reunir todos los parámetros en un array `args`:

```js run
function sumAll(...args) { // args is the name for the array
function sumAll(...args) { // args es el nombre del array
let sum = 0;

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

We can choose to get the first parameters as variables, and gather only the rest.
Podermos elegir obtener los primeros parámetros como variables, y juntar solo el resto.

Here the first two arguments go into variables and the rest go into `titles` array:
Aquí los primeros dos argumentos se populan en variables y el resto populan el `titles`:

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

// the rest go into titles array
// i.e. titles = ["Consul", "Imperator"]
alert( titles[0] ); // Consul
alert( titles[1] ); // Imperator
// el resto va en el array titles
// por ejemplo titles = ["Cónsul", "Emperador"]
alert( titles[0] ); // Cónsul
alert( titles[1] ); // Emperador
alert( titles.length ); // 2
}

showName("Julius", "Caesar", "Consul", "Imperator");
showName("Julio", "Cesar", "Cónsul", "Emperador");
```

````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="Los parámetros rest deben ir al final"
Los parámetros rest recogen todos los argumentos sobrantes, por lo que el siguiente código no tiene sentido y causa un error:

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

The `...rest` must always be last.
`...rest` debe ir siempre último.
````

## The "arguments" variable
## La variable "arguments"

There is also a special array-like object named `arguments` that contains all arguments by their index.
También existe un objeto símil-array especial llamado `arguments` que contiene todos los argumentos indexados.

For instance:
Por ejemplo:

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

// it's iterable
// arguments es iterable
// for(let arg of arguments) alert(arg);
}

// shows: 2, Julius, Caesar
showName("Julius", "Caesar");
// muestra: 2, Julio, Cesar
showName("Julio", "Cesar");

// shows: 1, Ilya, undefined (no second argument)
// muestra: 1, Ilya, undefined (no hay 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.
Antiguamente, los parámetros rest no existían en el lenguaje, y usar `arguments` era la única manera de obtener todos los argumentos de una función, sin importar la cantidad de ellos.

And it still works, we can use it today.
Y aún funciona, podemos usarlo hoy en día.

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.
Pero la desventaja es que a pesar de que `arguments` es símil-array e iterable, no es un array. No soporta los métodos de array, no podemos ejecutar `arguments.map(...)` por ejemplo.

Also, it always contains all arguments. We can't capture them partially, like we did with rest parameters.
Además, siempre contiene todos los argumentos. No podemos capturarlos parcialmente, como hicimos con los parámetros rest.

So when we need these features, then rest parameters are preferred.
Por lo tanto, cuando necesitemos estas funcionalidades, los parámetros rest son preferidos.

````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="Las funciones flecha no poseen `\"arguments\"`"
Si accedemos el objeto `arguments` desde una función flecha, toma su valor dela función "normal" externa.

Here's an example:
Aquí hay un ejemplo:

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

As we remember, arrow functions don't have their own `this`. Now we know they don't have the special `arguments` object either.
Como recordamos, las funciones flecha no tienen su propio `this`. Ahora sabemos que tampoco tienen el objeto 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 obtener un array de la lista de parámetros.

But sometimes we need to do exactly the reverse.
Pero a veces necesitamos hacer exactamente lo opuesto.

For instance, there's a built-in function [Math.max](mdn:js/Math/max) that returns the greatest number from a list:
Por ejemplo, existe una función nativa [Math.max](mdn:js/Math/max) que retorna el número mas grande de una lista:

```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?
Ahora bien, supongamos que tenemos un array `[3, 5, 1]`. ¿Cómo ejecutamos `Math.max` con él?

Passing it "as is" won't work, because `Math.max` expects a list of numeric arguments, not a single array:
Pasando la variable no funcionará, porque `Math.max` espera una lista de argumentos numéricos, no un único array:

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

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.
Y seguramente no podremos manuamente listar los items en el código `Math.max(arr[0], arr[1], arr[2])`, porque tal vez no sepamos cuantos son. A medida que nuestro script se ejecuta, podría haber muchos elementos, o podría no haber ninguno. Y eso podría ponerse feo.

*Spread operator* to the rescue! It looks similar to rest parameters, also using `...`, but does quite the opposite.
¡*Operador Spread* al rescate! Luce similar a los parámetros rest, utilizando también `...`, pero hace exactamente lo opuesto.

When `...arr` is used in the function call, it "expands" an iterable object `arr` into the list of arguments.
Cuando `...arr` es usado en el llamado de una función, "expande" el objeto iterable `arr` en una lista 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 convierte el array en una lista de argumentos)
```

We also can pass multiple iterables this way:
También podemos pasar múltiples iterables de esta manera:

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

We can even combine the spread operator with normal values:
Incluso podemos combinar el operador spread con valores normales:


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

Also, the spread operator can be used to merge arrays:
Además, el operador spread puede ser usado para combinar arrays:

```js run
let arr = [3, 5, 1];
Expand All @@ -190,56 +190,56 @@ 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, luego arr, después 2, después arr2)
```

In the examples above we used an array to demonstrate the spread operator, but any iterable will do.
En los ejemplos de arriba utilizamos un array para demostrar el operador spread, pero cualquier iterable funcionará también.

For instance, here we use the spread operator to turn the string into array of characters:
Por ejemplo, aquí usamos el operador spread para convertir la cadena en un array de caracteres:

```js run
let str = "Hello";
let str = "Hola";

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

The spread operator internally uses iterators to gather elements, the same way as `for..of` does.
El operador spread utiliza internamente iteradores para iterar los elementos, de la misma manera que `for..of` hace.

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]`.
Entones, para una cadena `for..of` retorna characters y `...str` se convierte en `"H","o","l","a"`. La lista de caracteres es pasada a la inicialización del array `[...str]`.

For this particular task we could also use `Array.from`, because it converts an iterable (like a string) into an array:
Para esta tarea en particular también podríamos haber usado `Array.from`, ya que convierte un iterable (como una cadena de caracteres) en un array:

```js run
let str = "Hello";
let str = "Hola";

// Array.from converts an iterable into an array
alert( Array.from(str) ); // H,e,l,l,o
// Array.from convierte un iterable en un array
alert( Array.from(str) ); // H,o,l,a
```

The result is the same as `[...str]`.
El resultado es el mismo que `[...str]`.

But there's a subtle difference between `Array.from(obj)` and `[...obj]`:
Pero hay una sutil diferencia entre `Array.from(obj)` y `[...obj]`:

- `Array.from` operates on both array-likes and iterables.
- The spread operator operates only on iterables.
- `Array.from` opera con símil-arrays e iterables.
- El operador spread solo opera con iterables.

So, for the task of turning something into an array, `Array.from` tends to be more universal.
Por lo tanto, para la tarea de convertir algo en un array, `Array.from` tiende a ser mas universal.


## Summary
## Resumen

When we see `"..."` in the code, it is either rest parameters or the spread operator.
Cuando veamos `"..."` en el código, son los parámetros rest o el operador spread.

There's an easy way to distinguish between them:
Hay una manera fácil de distinguir entre ellos:

- 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.
- Cuando `...` se encuentra al final de los parámetros de una función, son los "parámetros rest" y recogen el resto de la lista de argumentos en un array.
- Cuando `...` está en el llamado de una función o similar, se llama "operador spread" y expande un array en una lista.

Use patterns:
Patrones 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.
- Los parámetros rest son usados para crear funciones que acepten cualquier número de argumentos.
- El operador spread es usado para pasar un array a funciones que normalmente requieren una lista de muchos argumentos.

Together they help to travel between a list and an array of parameters with ease.
Ambos ayudan a ir entre una lista y un array de parámetros con facilidad.

All arguments of a function call are also available in "old-style" `arguments`: array-like iterable object.
Todos los argumentos de un llamado a una funcion están también disponibles en el "viejo" `arguments`: un objeto símil-array iterable.