Introducción al JavaScript de ECMAScript 6

Escrito por el , actualizado el .
javascript planeta-codigo programacion
Enlace permanente Comentarios

Con ECMAScript 6 se han incorporado al lenguaje varias novedades como nuevas palabras reservadas para definir variables y constantes, símbolos, interpolación de variables en cadenas, desestructuración, forma abreviada para declarar funciones, nueva sintaxis más sencilla para definir clases, objetos de tipo Map y Set, Promises como alternativa a callbacks, el protocolo Iterator y generadores, además de algunas otras cosas que si como yo no habías dedicado tiempo a aprender mejor JavaScript aún te resulten novedosas.

JavaScript

Hasta ahora como desarrollador web durante prácticamente toda mi vida laboral no había dedicado tiempo a conocer en más detalle el lenguaje de programación JavaScript usado en los navegadores web. Mucho de lo que necesitaba me era suficiente con librerías como jQuery o underscore. Ahora algunas páginas web tienen un peso importante en el lado cliente y ante esta necesidad el lenguaje JavaScript está evolucionando e incorporando nuevas características como las definidas en sus especificaciones de ECMAScript.

Para aprender en mucho más en detalle lo poco que conocía de JavaScript he leído el libro Learning JavaScript que cubre las novedades de ECMAScript 2015 también conocido como ECMAScript 6 (ES6). Después de leerlo diré que es un libro que me ha gustado mucho y considero que es adecuado tanto para alguien que pueda estar aprendiendo a programar como para alguien que ya conoce otros lenguajes de programación explicando los conceptos sin complicaciones.

Las últimas versiones de los navegadores Chrome y Firefox ya soportan todo lo que describo a continuación y que está más detalladamente explicado en el libro. Para los navegadores que aún no soportan todo como en los dispositivos móviles hay compiladores o transpilers para traducir de ECMAScript 6 a ECMAScript 5. En un entorno en el que sepamos se usa solo Chrome o Firefox como en una intranet o una aplicación de uso interno en una organización podemos utilizar estas novedades y si es una aplicación accesible por cualquier usuario desde internet podemos hacer la conversión de ECMAScript 6 a ECMAScript 5 con gulp o grunt.

Estas son gran parte de las novedades que he anotado al leer el libro Learning JavaScript. Para profundizar sobre JavaScript la documentación de Mozilla Developer Network está muy bien como manual de referencia donde hay más ejemplos y comentarios más extensos de los que hago en cada sección.

Definición de variables

Para solventar las deficiencias de las variables declaradas con var hay dos nuevas palabras reservadas let para declarar variables que cambian de valor y const para constantes. También se pueden declarar símbolos que son identificadores de tipos únicos e inmutables.

El problema de las variables declaradas con var está en que tienen ámbito de función con let no existe hasta que es declarada. Las variables con var son declaradas al principio del ámbito de la función o en el ámbito global.

1
2
3
let i = 1;
const string = '¡Hola mundo!';
const symbol = Symbol('descripcion');
variables.js

Interpolación de variables en cadenas

La interpolación de variables en cadenas facilita la construcción de strings y hace el código más legible. Las plantillas se definen con comillas de acento grave `.

1
2
3
4
const now = new Date(Date.now());
const message = `¡Hola ${now.getFullYear()}!`;
console.log(message);
// ¡Hola 2016!
interpolation.js

Desestructuración

Se ha incorporado la asignación desestructurada pudiendo hacer cosas como las siguientes en las asignaciones y en las llamadas a las funciones.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Arrays
const array = [1, 2];
const [a, b] = array;
console.log(`${a}, ${b}`);
// 1, 2

// Objects
const object = { name: 'Juan', age: 30 };
const {name, age} = object;
console.log(`${name}, ${age}`);
// Juan, 30

// Functions
function whois({displayName: displayName, fullName: { firstName: name }}){
  console.log(`${displayName} is ${name}`);
}

var user = {
  id: 42,
  displayName: "jgarcia",
  fullName: {
      firstName: "Juan",
      lastName: "García"
  }
};

whois(user);
// Juan Garcia is jgarcia 
destructuring.js

Operador spread

El operador spread permite a una expresión se expandida en lugares donde se esperan múltiples argumentos como en llamadas a funciones, múltiples elementos para literales de arrays o múltiples variables para asignación desestructurada.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const array1 = [1, 2, 3];
const array2 = [...array1, 4, 5, 6]
console.log(array2);
// Array [ 1, 2, 3, 4, 5, 6 ]

function func(x, y, z) {
  console.log(`${x}, ${y}, ${z}`);
}
func(...array1);
// 1, 2, 3
spread.js

Bucles con in y of

Usando el iterador in en un bucle recorremos las propiedades de un objeto y con el iterador of podemos recorrer cualquier objeto iterable. Cualquier objeto que definamos podemos hacerlo iterable cumpliendo el protocolo Iterable.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const object = { name: 'Juan', age: 30 };
const array = [1, 2, 3];

for (let property in object) {
  console.log(`${property}: ${object[property]}`);
}
// name: Juan 
// age: 30

for (let property of array) {
  console.log(`${property}`);
}
// 1
// 2
// 3
iterator-in-of.js

Funciones

En JavaScript definir funciones es una parte muy importante de la esencia del lenguaje, ahora hay una forma corta de definir funciones.

1
2
3
const func = () => { console.log('¡Hola mundo!'); }
func();
// ¡Hola mundo!
arrow-functions.js

Arrays

El tipo Array tiene muchos métodos y funciones adecuadas para la programación funcional como map, filter o reduce y también push, pop, shift, unshift, forEach, slice, splice, fill, copyWithin, findIndex, lastIndexOf, indexOf, reverse, sort, some, every, join o concat. Funciones que antes no estaban presentes y para suplir su ausencia usábamos la librería underscore.

Métodos de la clase Function

Teniendo en una variable de tipo Function podemos llamarla con call incluyendo un parámetro que se considerará el valor de la referencia this dentro de la función. Con apply los argumentos serán los definidos en un array aunque con la sintaxis spread esta función puede caer en desuso. Con bind podemos asociar a la función la referencia que siempre se tomará como this.

Nueva sintaxis para clases

Anteriormente en JavaScript ya se podían definir clases haciendo uso de la propiedad prototype aunque su sintaxis ahora se ha simplificado y hecho más parecida a otros lenguajes además de definir propiedades con su método getter y setter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Vehiculo {
  constructor() {
    this._marca = 'Seat';
    this._color = 'rojo';
    this._kilometros = 100;
  }
  get color() {
    return this._color;
  }
  set color(c) {
    this._color = c;
  }
}

class Coche extends Vehiculo {
  get kilometros() {
    return this._kilometros;
  }
  set kilometros(k) {
    this._kilometros = k;
  }
}

const coche = new Coche();
console.log(coche.color);
// rojo
classes.js

Objetos Map y Set

Los objetos pueden ser utilizados como mapas pero a veces utilizar un objeto no es deseable como contenedor de datos, para ello se definen los Map que son clases que a través de una clave se accede a un valor y Set para colecciones sin elementos repetidos.

Algunas funciones de la clase Map son get, set, has, size, keys, values, entries, forEach, delete, clear y size. Algunas de la clase Set son add, has, forEach, delete y size.

Operadores instanceof y typeof

Con instanceof se puede comprobar si una variable es de un cierto tipo, si su cadena de prototipos incluye la función indicada. Con typeof se puede conocer el tipo de dato de una variable.

1
2
3
4
5
6
7
8
9
console.log(coche instanceof Object); // true
console.log(coche instanceof Coche);  // true

console.log(typeof coche);            // object
console.log(typeof 1);                // number
console.log(typeof '¡Hola mundo!');   // string
console.log(typeof true);             // boolean
console.log(typeof symbol);           // symbol
console.log(typeof fibonacci);        // function
instanceof-typeof.js

Excepciones

JavaScript soporta gestionar ciertas circunstancias de error con excepciones y con la construcción try catch finally similar a la existente en lenguajes como Java.

Callback y Promise

Algunas tareas las manejamos usando funciones callback, funciones que se pasan como argumento y que son llamadas en algún momento. La programación con callback se hace complicada en la programación asíncrona cuando se anidan varias funciones. Con los objetos Promise el código de la programación asíncrona es más legible.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
const promise = new Promise(function(resolve, reject) {
    resolve();
});

promise.then(function() {
    console.log('then');
}).catch(function() {
    console.log('catch');
});
// then
callback-promise.js

Generators

Los objetos Generator que se basan en el protocolo Iterator pueden establecer una comunicación entre el generador y el código que lo llama con la palabra reservada yield que retorna el valor del generador y la función next() del iterador que puede proporcionar una parámetro usable en el generador. Las funciones generadoras se declaran poniendo un * después de la palabra function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function* fibonacci() {
  var fn1 = 0;
  var fn2 = 1;
  while (true) {
    var current = fn1;
    fn1 = fn2;
    fn2 = current + fn1;
    var reset = yield current;
    if (reset) {
        fn1 = 0;
        fn2 = 1;
    }
  }
}


var sequence = fibonacci();
console.log(sequence.next().value);     // 0
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
console.log(sequence.next().value);     // 3
console.log(sequence.next().value);     // 5
console.log(sequence.next().value);     // 8
console.log(sequence.next(true).value); // 0
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 1
console.log(sequence.next().value);     // 2
generator.js

Otros métodos nuevos de la clase Object son freeze que impide añadir nuevas propiedades al objeto, eliminar existentes o modificar sus valores haciendo al objeto inmutable. Con seal se previene únicamente añadir nuevas propiedades.

Misc

Declarando el modo esctricto con ‘use strict’; evitamos algunos de los errores que podemos cometer al usar JavaScript como declarar una variable en un ámbito global cuando no es nuestra intención. Con el método toString() de los objetos podremos proporcionar una representación de un objeto más descriptiva.

Manipulación DOM

Es raro que para manipular el árbol DOM que representa el HTML cargado en el navegador no usemos la librería jQuery pero para casos básicos o cuando no podemos usar esa librería o queremos esa dependencia podemos hacer uso de las funciones incorporadas en el propio navegador y algunas funciones declaradas en el objeto Document. Algunos métodos del objeto Documento son getElementById, getElementsByClassName, getElementsByTagName, querySelector y querySelectorAll.

Para manipular el texto de un nodo se usa la propiedad textContent de la interfaz Node y para incluir en el nodo contenido HTML la propiedad innerHTML de la interfaz Element.

Con createElement de Document mediante código podemos crear nuevos elementos y con appendChild o insertBefore de Node insertarlos en el árbol DOM. Con la propiedad classList y los métodos add y remove podemos añadir clases a un nodo y con dataset acceder a los atributos data- de la etiqueta.

Eventos

Los navegadores definen más de 200 eventos ante los que podemos reaccionar, uno de los más típicos es el click en un botón. A un Element de la página y con el método addEventListener() se pueden asociar eventos.

Eventos como el click en algunos elementos tienen definido un comportamiento por defecto, para evitar ejecutar ese comportamiento por defecto disponemos de la función preventDefault.

Los manejadores de eventos se van recorriendo primero en modo captura desde la raíz hasta el nodo del árbol DOM donde se ha producido el evento y posteriormente en modo burbuja desde el nodo donde se ha producido el evento hasta la raíz. Con stopPropagation se puede cancelar la propagación del evento, realmente la propagación se sigue realizando pero el evento se marca como cancelado. Con stopImmediatePropagation se puede parar la propagación completamente, parando incluso la propagación con el evento cancelado.

Todos estos ejemplos funcionan en los navegadores Firefox y Chrome pudiendo probarlos en la consola JavaScript que incorporan para los desarrolladores. En la página es6-features hay una lista completa de todas las nuevas características de ECMAScript 6.


Comparte el artículo: