ES6: el remozado JavaScript. Parte II: funciones, objetos y arrays

Índice de contenidos

El objetivo de este artículo es introducir las novedades de ES6 relativas a Funciones, Objetos y Arrays.

4. Funciones

Las funciones es uno de los apartados dentro de la especificación donde se han hecho más cambios. Veámoslos

4.1. Valores por defecto

Una cosa que siempre ha tenido JavaScript, y que ha sido fruto de controversia entre los programadores de otros lenguajes, es que se puede definir una función con más parámetros que con los que se la llama.

Pero ahora, como pasaba en otros lenguajes EcmaScript como Flex, se pueden declarar valores por defecto para esos parámetros.

A las funciones en JavaScript que pueden recibir un número variable de parámetros se les llama funciones variádicas. Y es uno de los puntos que aporta potencia al lenguaje, pero que lo convierte en incómodo a aquellos desarrolladores acostumbrados a otros lenguajes de programación, que para nada esperan este comportamiento.

4.2. Parámetro REST y operador SPREAD

Ahora en una función se permite que el último argumento que se le pasa, sea especial y se denota con tres puntos suspensivos. Eso nos indica que este último argumento, recibirá todos los parámetros de más de la función en forma de array:

¿Y la operación contraria? Imaginemos que lo que tenemos es una función variádica que espera un número variable de parámetros en lugar de un array. Podemos convertir fácilmente el array a una lista de parámetros con el operador SPREAD, que también se denota con tres puntos suspensivos.

Esto puede parecer que da lugar a equívocos, pero fijémonos que uno se utiliza para definir una función, y el otro para invocarla.

4.3. Funciones Arrow

Se denominan funciones arrow, se denotan por el símbolo => y se utilizan de la siguiente manera. Las siguientes expresiones son equivalentes

Se utiliza mucho en las funciones anónimas que se definen como callbacks de otras funciones porque la función arrow sí preserva el contexto del this, al contrario de lo que pasa con las funciones estándar.

Por ejemplo, muchas veces habremos visto código de terceros que hacen cosas como var that = this y luego se refieren a ese that. Eso lo hacen porque la palabra this hace referencia al contexto del callback y no de la función externa. Veamos un ejemplo.

Sin embargo, con una función Arrow quedaría:

Cuando la función arrow sólo recibe un argumento, no es necesario escribir paréntesis:

Pero sí cuando no hay argumentos o son más de uno.

5. Objetos y Arrays

5.1. Forma abreviada para quitar repeticiones

En numerosas ocasiones nos hemos encontrado devolviendo un objeto con nombres y valores repetidos, donde el primero hace referencia a la propiedad, y el segundo es la variable con su valor

Pero ahora es posible devolver una versión abreviada, donde la propiedad será como el nombre de la variable que contiene el valor. En el siguiente ejemplo, ambas funciones son equivalentes:

Y también funciona en la asignación de variables:

En lugar de

5.2. Asignación por Destructuring

Se pueden asignar variables recorriendo las propiedades de un objeto de una en una, o bien se puede usar la asignación por destructuring, donde se asigna a cada variable la propiedad correspondiente.

No es obligatorio usar todas las propiedades del objeto. Se puede utilizar sólo una parte para hacer la asignación por destructuring.

La asignación por destructuring también funciona para arrays.

¿y funcionará con el operador Spread?

Pues sí que funciona, al menos en Google Chrome, aunque según la especificación, eso es de la próxima versión de EcmaScript ES7.

5.3. Iteraciones: for… in vs for… of

En las versiones previas de JavaScript ya se podía recorrer un array con bucles de tipo for… in

Realmente, recorre todas las propiedades enumerables de un objeto en un orden indeterminado.

De los dos bucles for, el primero nos obliga a acceder a la propiedad mediante la triquiñuela del eval(), porque si accedemos directamente mediante jugador.propiedad, no evalúa el valor de “propiedad” en cada vuelta del bucle, y busca literalmente el atributo llamado “propiedad”, y nos devolvería undefined.

Pero todos los objetos pueden recorrerse como arrays asociativos. Es decir, podemos acceder al nombre de ambas maneras.

Y esto es lo que usamos en el segundo bucle.

Pero ¿y qué pasa si lo que tenemos es un array de objetos?

Pero en ES6 existe una nueva forma de recorrer con for…of, que en lugar de por índice, recorre directamente los objetos que contiene:

Esto de for…of lo podemos hacer sobre los arrays porque son objetos iterables. Pero no es lo habitual en JavaScript. Si definimos un objeto, e intentamos recorrer sus propiedades, nos dará un error similar al siguiente: “TypeError: jugador[Symbol.iterator] is not a function”.


Pero siempre podemos crearlo. Veamos cómo.

5.4. Entendiendo Iteradores, y como crearlos

Hay algunos tipos de objetos que tienen implementado el iterador. Vamos a ver qué pinta tiene este iterador


Lo primero que se puede observar, es que la variable equipo, que es un array, sí implementa Symbol.iterator. Y al preguntar por iterador.next() nos devuelve un objeto con dos propiedades: value, que tiene el primer elemento del array, y done un booleano que nos indica si ya hemos recorrido todos los elementos.

Pero si usamos un objeto en lugar de un array, esto no funcionará porque no implementa un iterador. Pero podemos definirlo nosotros. Imaginemos el siguiente objeto no iterable:

Y queremos iterar sobre sus atributos. Podríamos definir el siguiente iterador:

Una vez ya definido, podríamos recorrer las propiedades del objeto con un bucle de tipo for… of:


5.5. Generadores

En esta nueva versión de JavaScript se introducen los generadores, que tienen todo el aspecto de una función, pero con algunas particularidades. La primera, y que es la que lo define, es que tras la palabra reservada function hay un asterisco *. Y en lugar de return usa la palabra reservada yield. Además, todo generador implementa un iterador.

Cuando se invoca a un generador, como en el ejemplo anterior, no hace nada de nada.

Como los iteradores, funciona cuando se llama a su método next(), entonces devuelve el primer yield, y se guarda el estado a la espera de que en algún momento se vuelva a llamar a next(). Cuando se llame a next() por segunda vez, devolverá el segundo yield. Y así hasta que no haya más.


Esto tiene múltiples implicaciones, ligadas a la preservación del estado y la asincronía. Una que se me ocurre es para implementar un asistente, wizard o sistema de pasos:

Y otra de las más utilizadas es para escribir el iterador que poníamos de ejemplo en el punto anterior, pero de una forma mucho más simple:

5.6. Los nuevos tipos Map y WeakMap

En esta versión de JavaScript se introducen cuatro tipos nuevos de objetos: Map, WeakMap, Set y WeakSet.

Los mapas son un conjunto de pares clave / valor que implementan algunas operaciones:

  • para añadir elementos al mapa
  • para obtener un elemento del mapa
  • para consultar si está un elemento en el mapa
  • para quitar un elemento del mapa
  • para vaciar el mapa

En el caso concreto de los mapas, son iterables, y admiten pares de objetos, tanto en las claves como en los valores:

Por el contrario los WeakMap son un tipo de mapas “débiles”. La primera diferencia es que las claves sólo pueden ser objetos. Nunca strings. Tampoco son iterables, y como tal no puedes consultar sus claves con Object.keys(). Además, hay que tener en cuenta que sus objetos se encuentran referenciados de forma “weak” (débil). Esto quiere decir, que el objeto que forma parte de la clave, si no es referenciado por nadie más que el WeakMap, es susceptible de que el Garbage Collector lo elimine.

Por tanto, el uso de los WeakMap tienen sus pros y sus contras.

En contra tienen que no son colecciones que se puedan recorrer con bucles de tipo for…of, hay que conocer la clave a priori para recuperar su valor. Tiene el peligro de que si nadie referencia a la clave, se pierda el valor asociado. A cambio, tiene la ventaja de no permitir memory leaks.

5.7. Los nuevos tipos Set y WeakSet

Al igual que los mapas, los conjuntos también se introducen en esta especificación de ES6. Consisten en colecciones de objetos o valores primitivos y no se pueden repetir.

Los WeakSet son como los Set pero con la misma línea argumental que los WeakMap:

  • No implementan un iterador
  • Sólo pueden contener objetos
  • Y su referencia a sus valores es débil
Este post está formado de tres partes y en breve se publicará la siguiente: ES6: el remozado JavaScript. Parte III: clases y otras novedades del lenguaje