Cómo funciona y cómo usar los operadores Spread y Rest
En el artículo de hoy vamos a hablar de una de las características de la versión ES6 (ECMAScript 2015) de JavaScript que es el operador Spread así como el operador Rest.
Estas características pueden ser muy útiles cuando se desarrolla y trabaja con los marcos de trabajo del front-end. Explicaremos como puedes usarlo en la práctica cuando copies y fusiones arrays y literales de objetos, insertas datos, con los beneficios de hacer tu código más limpio. Vamos a entrar en ello y ver cómo funciona.
Definición y sintaxis del Spread operador
El operador Spread aparece como tres puntos (...) y lo que hace es tomar el grupo en expresión e intentar "extenderlo" a múltiples valores.
Puede llevar los elementos de una matriz existente a una nueva matriz. Cuando tenemos una iterable como por ejemplo una matriz con múltiples valores, expande los valores de esa matriz en elementos individuales.
Se utiliza principalmente en la matriz de variables donde se espera que haya más de un valor.
var variable = [...valor];
Hay básicamente 3 ocasiones en las que se puede usar spread - En los literales de la matriz, en los literales de los objetos y en las llamadas a funciones.
También se puede usar para hacer copias de objetos, así que empecemos con eso.
Copia de una matriz u objeto
Hacer copias de los no-primitivos puede ser difícil. Si copias una primitiva, como un número o una cadena, crearás una copia real, pero con objetos es diferente.
Vamos a crear una matriz con 3 elementos. Luego hacemos una copia superficial de ese array usando el operador de dispersión y el tercer array es un nuevo array, pero básicamente es el mismo array que el array1, porque cuando asignas el array1 al array3, se copia la referencia al array1, no los valores en sí mismos.
Eso es copia de JavaScript por referencia. Cuando hagamos cambios en el array1, también el array3 será alterado, porque la referencia de la variable es el mismo lugar en la memoria. Con el operador de difusión, en realidad creamos un nuevo array completamente - los valores se copiarán y JS manejará este nuevo objeto como una entrada separada, como una nueva entrada declarada en la memoria. Al hacer cambios en el nuevo array2, el original no se vería afectado. Esto se llama copia profunda.
let array1 = ['h', 'e', 'y']; let array2 = [...array1]; let array3 = array1 console.log(array2); //Array(3) [ "h", "e", "y" ] array1.shift(); console.log(array1); //Array [ "e", "y" ] console.log(array2); //no hay cambios - Array(3) [ "h", "e", "y" ] console.log(array3); //Array [ "e", "y" ]
Nota: La propagación sólo tiene un nivel de profundidad cuando se copia una matriz o un objeto, no realiza una copia profunda de estructuras de datos anidados. (para eso necesitarías const myClone = JSON.parse(JSON.stringify(objToClone))
El siguiente ejemplo muestra la creación de una copia de un objeto.
const myName = { firstName :'Tibor', middleName : '', lastName : 'Kopca' } const newName = {...myName} //usando spread copiamos el objeto newName.middleName = 'Tiburon' //añadimos un nuevo atributo al objeto copiado console.log("El antiguo nombre era :"+myName.firstName+" "+myName.middleName+" "+myName.lastName) //El antiguo nombre era :Tibor Kopca console.log("El nuevo nombre es :"+newName.firstName+" "+newName.middleName+" "+newName.lastName) //El nuevo nombre es :Tibor Tiburon Kopca
Se esparcen en los literales de la matriz
Spread operador puede ser usado en muchos casos, como cuando queremos expandir, copiar, concatenar el primer objeto.
Podemos fusionar efectivamente dos o más iterables sin necesidad del método concat.
Aquí es un ejemplo del uso cuando necesitamos añadir elementos de array1 y array2 juntos, combinándolos en uno.
Nota: para los datos grandes usar el operador spread resultará más lento comparado con el método nativo concat()
.
let array1 = [1,2,3,4,5,6]; let array2 = [7,8,9]; let arrayConcat = array1.concat(array2); console.log(arrayConcat); //Array(9) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ] let arraySpread = [...array1, ...array2]; //Combinando ambos conjuntos en uno console.log(arraySpread); //Array(9) [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
De la misma manera si queremos expandir una matriz para más valores:
let arrayExpanded = [...array2, 10, 11]; console.log(arrayExpanded); //Array(5) [ 7, 8, 9, 10, 11 ]
O podemos concatenar argumentos de cadena. Noten la diferencia en las dos últimas filas.
console.log("Hello", "Ma-no.org"); //Hello Ma-no.org //concat() text let text = ["Hello", "world", "!"]; console.log(text); //Array(3) [ "Hello", "world", "!" ] console.log(...text); //Hello world !
Aquí podemos ver que las cadenas también son iterativas.
console.log(..."VICTORY!"); // V I C T O R Y !
Aquí hay otro ejemplo de conjuntos concatenados en un gran conjunto.
El orden en que se agregan los conjuntos es importante en este caso.
let pets = ['cat', 'dog', 'bird']; let kids = ['Peter', 'Suzan']; const fullfamily = [...kids, ...pets]; console.log(fullfamily); //Array(5) [ "Peter", "Suzan", "cat", "dog", "bird" ]
Spread in Llamadas de la función
Veamos algunos ejemplos cuando se trabaja con un objeto matemático. Aquí encontraremos, por ejemplo, el mínimo de una lista de argumentos separados por comas: los números del 0 al 4, y el número más bajo es el "0". Sin argumentos será el infinito, etc.
Pero con la lista de números en la matriz no funcionará y devolverá NaN. Ahora podemos hacer uso del Spread operador, que nos permite pasar cada número de la matriz en la función matemática como argumentos individuales.
console.log(Math.min(0,1,2,3,4)); //0 console.log(Math.min()); //infinity let arrayNumbers = [0,1,2,3,4]; console.log(Math.min(arrayNumbers)); //NaN let arrayNumbersWithSpread = [0,1,2,3,4]; console.log(Math.min(...arrayNumbersWithSpread)); //0
Matriz a los argumentos
Ahora, lo siguiente es interesante. Cuando usas spread para acceder al contenido de un iterable, te devolverá el contenido.
En lugar de pasar cada argumento, puedes pasar en un array con todos los argumentos. El resultado será el mismo que si pasaras todos los argumentos uno por uno.
const myTeam = ['Ivet', 'Ismael', 'Luigi', 'Silvia'] function printTeam(person1, person2, person3){ return document.write(`Ma-no has the best team with - ${person1}, ${person2}, ${person3}.`) } printTeam(...myTeam)
Literales de objeto y Spread
Al igual que con las matrices, podemos usar la dispersión para combinar y copiar objetos, es el mismo principio.
Digamos que tenemos un objeto que tiene un nombre, el uso de Spread seguido del nombre del objeto accederá a la propiedad (contenido) del objeto y lo cerrará de esta manera:
const myName = { firstName :'Tibor', middleName : '', lastName : 'Kopca' } console.log({...myName}) //Object { firstName: "Tibor", middleName: "", lastName: "Kopca" const newName = {...myName} //usando spread copiamos el objeto newName.middleName = 'Tiburon' //añadimos un nuevo atributo al objeto copiado console.log("El antiguo nombre era :"+myName.firstName+" "+myName.middleName+" "+myName.lastName) //El antiguo nombre era :Tibor Kopca console.log("El nuevo nombre es :"+newName.firstName+" "+newName.middleName+" "+newName.lastName) //El nuevo nombre es :Tibor Tiburon Kopca
Por supuesto, al igual que con las matrices, el Spread operador puede ser utilizado para concatenar objetos. Como spread eran abreviaturas del método Object.assign()...
const obj1 = {title : 'The Wall'} const obj2 = {author : 'Pink Floyd'} const music = {...obj1, ...obj2} console.log(music) //Object { title: "The Wall", author: "Pink Floyd" }
Desestructuración
Primero empiece con la desestructuración, porque esto lleva directamente al operador de Rest. Como su nombre indica, la desestructuración consiste en tomar un objeto o un conjunto y convertirlo en objetos más pequeños o elementos más pequeños con menos variables. En la segunda parte tenemos una función que devuelve la suma y la deducción de 2 números. Podemos desestructurar su retorno en 2 variables como se ve aquí abajo.
let letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] const [element1, element2, element3] = letters console.log(element1, element2, element3) //a b c function addAndDeduct(num1, num2){ return [num1 + num2, num1 - num2] //this will return first number in array summed and the second deducted } const [sum, deduct] = addAndDeduct(1,5) console.log(sum) //this will print variable sum which is 6 console.log(deduct) //-4
Operador Rest
Muy pronto mencionaremos el operador Rest, que se ve exactamente como el operador de la difusión. Nos permite representar un número indefinido de argumentos como una matriz - básicamente recoge todos los argumentos restantes de una función en una matriz. Funciona de forma similar al operador de dispersión, pero hay una ligera diferencia. Sólo el último parámetro puede ser un "parámetro Rest". Veamos algunos ejemplos de su uso, y noten que el resultado es un array.
En este ejemplo, el primer argumento se asigna a a y el segundo a b, por lo que estos argumentos nombrados se utilizan de forma normal. Sin embargo, el tercer argumento, "args", será una matriz que contiene el 3º, 4º, 5º, 6º... n-ésimo - tantos argumentos como el usuario incluya.
function useRest(a, b, ...args) { console.log(args); } useRest(1,2,3,4,5); //Array(3) [ 3, 4, 5 ]
Así que los tres puntos ( ...) representan tanto el operador Spread como el parámetro Rest. Aquí están las principales diferencias: El operador Spread desempaqueta los elementos. El parámetro Rest empaqueta los elementos en una matriz. Los parámetros de Rest deben ser el último argumento de una función. Sin embargo, el Spread operador puede estar en cualquier lugar.
function foo(a, ...rest, b) { //producira un error }
Conclusión
En este tutorial aprendimos sobre los operadores de Spread y Rest de JavaScript y cómo manejarlos.
Por último, aconsejamos comprobar la compatibilidad del navegador en los documentos web de MDN, si te ha gustado este artículo y si estás dispuesto a utilizar el operador de difusión en la práctica.
Eso es todo, esperamos que hayas disfrutado del artículo.
Imagen de Pixabay