ES6: Spread Operator en JavaScript
Tags: javascript, es6, spanish, webdev
Published: 2020-07-30 15:28:45

Continuando con la serie de post de JavaScript moderno llegamos a un tema bastante importante, sobre todo si trabajamos con frameworks o librerías como React.js. El **spread operator** u operador de propagación por su traducción al español nos permite realizar acciones bastante interesantes tanto con arrays como con objetos, a grandes rasgos se podría decir que consta de 3 funcionalidades o usos:

**1. Concatenar arreglos y objetos.**
**2. Obtener copias independientes de arreglos y objetos.**
**3. Expandir o propagar un arreglo.**

## **Sintaxis**
La sintaxis del operador de propagación puede ser algo rara, consta de tres puntos seguidos (...) que preceden a un arreglo o un objeto:

```javascript
...arreglo
...objeto
```

Para comprender mejor este operador analizaremos ejemplos de los casos antes mencionados:

## **Spread Operator como concatenador de arreglos y objetos**
Posiblemente sea el uso más sencillo de comprender, imaginemos que tenemos 2 arreglos que necesitamos concatenar, podríamos usar el método `concat()` como se ve a continuación: 

```javascript
let arreglo_1 = [1,2,3];
let arreglo_2 = [4,5,6];
let arreglo_concatenado = arreglo_1.concat(arreglo_2);
console.log(arreglo_concatenado);
//salida: [1, 2, 3, 4, 5, 6]
```

Podríamos resolver el mismo ejemplo usando spread operator de la siguiente manera:

```javascript
let arreglo_1 = [1,2,3];
let arreglo_2 = [4,5,6];

let arreglo_concatenado =[...arreglo_1, ...arreglo_2]
console.log(arreglo_concatenado);
//salida: [1, 2, 3, 4, 5, 6]
```
El código se vuelve un poco más legible, además de poder unir más elementos al array concatenado tanto al inicio como al final:

```javascript
let arreglo_1 = [1,2,3];
let arreglo_2 = [4,5,6];

let arreglo_concatenado =[0, ...arreglo_1, ...arreglo_2, 7,8,9,10]
console.log(arreglo_concatenado);
//salida: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

Es posible concatenar las claves y los valores de un objeto de la siguiente manera: 

```javascript
let persona = {
  nombre: "Ana",
  edad: 25,
  peso:52
};

let datos_personales = {
  direccion: "Avenida Los Ejercitos",
  ci:4525896,
  getDatosPerosnales: function(){
    return `la direccion es: ${this.direccion} y el ci es: ${this.ci}`
  }
};


let full_person = {...persona, ...datos_personales};
console.log(full_person);

/* salida:
[object Object] {
  ci: 4525896,
  direccion: "Avenida Los Ejercitos",
  edad: 25,
  getDatosPerosnales: function(){
    return `la direccion es: ${this.direccion} y el ci es: ${this.ci}`
  },
  nombre: "Ana",
  peso: 52
}
*/
```

## **Spread Operator para obtener copias independientes de arreglos y objetos**

Imaginemos que el caso en el que necesitemos obtener una copia de un arreglo: 

```javascript
let array_nombres = ["Carlos","Pedro","Gabriela"];
let new_array_nombres = array_nombres;

console.log(array_nombres); // ["Carlos","Pedro","Gabriela"]
console.log(new_array_nombres); // ["Carlos","Pedro","Gabriela"]
```

Al mostrar por consola parece que logramos nuestro objetivo de una manera muy sencilla, pero si alteramos un item de nuestro array `new_array_nombres` pasa lo siguiente: 

```javascript
let array_nombres = ["Carlos","Pedro","Gabriela"];
let new_array_nombres = array_nombres;

new_array_nombres[1] = "Juan";
console.log(array_nombres); //["Carlos", "Juan", "Gabriela"]
console.log(new_array_nombres); //["Carlos", "Juan", "Gabriela"]
```

Actualizando un arreglo, sin querer actualizamos los 2, esto se da porque `new_array_nombres` no es una copia de `array_nombres`, son el mismo arreglo con diferentes nombres de variable. 

Para lograr obtener una copia independiente usamos el spread operator de la siguiente manera:

```javascript
let array_nombres = ["Carlos","Pedro","Gabriela"];
let new_array_nombres = [...array_nombres]; //copia independiente 

new_array_nombres[1] = "Juan";
console.log(array_nombres); //["Carlos", "Pedro", "Gabriela"]
console.log(new_array_nombres); //["Carlos", "Juan", "Gabriela"]
``` 

Ahora si `new_array_nombres` es una copia totalmente independiente de `array_nombres`, al actualizar el valor "Pedro" por "Juan" solo se ve afectado el `new_array_nombres` manteniéndose así, el arreglo original intacto. 

Es posible hacer copias independientes de objetos, como se muestra a continuación:

```javascript
let persona = {
  nombre: "Ana",
  edad: 25,
  peso:52
};

let new_persona = {...persona};

new_persona.nombre ="Alicia";

console.log(persona);
/*
[object Object] {
  edad: 25,
  nombre: "Ana",
  peso: 52
}
*/
console.log(new_persona);
/*
[object Object] {
  edad: 25,
  nombre: "Alicia",
  peso: 52
}
*/
```

## **Spread Operator para expandir o propagar un arreglo**
Finalmente, el operador de propagación se puede usar para parcelar los elementos de un arreglo, de hecho, es por esta característica que este operador recibe su nombre. Veamos un ejemplo:

```javascript
let array_primos=[2,3,5,7,11,13];
console.log(array_primos); // [2, 3, 5, 7, 11, 13]
console.log(...array_primos);
/*2
3
5
7
11
13
*/

```

> *`array_primos` es un arreglo mientras que `...array_primos` es una lista de elementos.*

### **¿Cuál es la diferencia entre un arreglo y una lista de elementos?**
Al principio hacer esta comparación puede confundir un poco porque desde el vamos ambos términos parecen sinónimos. 

Para evitar el exceso de teoría creo que es mejor explicar esta diferencia como siempre con ejemplos:

El objeto `Math` de javascript nos provee del método `max()` que retorna el número mayor de una **lista de elementos**

```javascript
let maximo = Math.max(1,2,3);
console.log(maximo); // 3
```
¿Qué sucede si tenemos un array de edades y deseamos pasarlo como parámetro al método `max()`? ¿Deberia funcionar no es verdad?

```javascript
let edades = [8,32,14,78,25,16];
let maximo = Math.max(edades);
console.log(maximo); // NaN
```
La consola no arroja un error, pero si un `NaN` (Not at Number) dándonos a entender que lo que esta almacenado en la variable `maximo` no es un número. ¿Porque sucede esto? La respuesta radica en el parámetro del método `max()`. `max()` recibe una **lista de parámetros** no un arreglo. Para corregirlo bastaría usar el spread operator de la siguiente manera: 

```javascript
let edades = [8,32,14,78,25,16];
let maximo = Math.max(...edades);
console.log(maximo); // 78
```
> *Convertimos el arreglo `edades` a una lista de parámetros haciendo uso del spread operator.*

### **Spread operator anidado**
En desarrollos de software de la vida real tocará destructurar arreglos u objetos anidados:

```javascript
const television = {
  tamaño: "grande",
  marca:"Sony",
  caracteristicas:{
    color:"rojo",
    peso:15
  }
};

const {tamaño,caracteristicas:{color}} = television;
console.log(tamaño, color); // grande, rojo
```

## **Conclusiones** ✔
* El Spread Operator u Operador de Propagación es una característica bastante novedosa y extremadamente útil en JavaScript moderno.
* A grandes rasgos se pueden hacer 3 acciones con el Spread Operator: 1) Concatenar arreglos y objetos. 2) Obtener copias independientes de arreglos y objetos. 3) Expandir o propagar un arreglo.
* En librerías y frameworks front-ent (Angular, React, Vue) el spread operator es bastante usado. 

---

## **Referencias** 📎
* https://www.youtube.com/watch?v=gFvWNjVy-wc
* https://www.youtube.com/watch?v=K77OCybbv24
* https://desarrolloweb.com/articulos/operador-spread-es6.html