ECMAScript 6

Introducción a ECMAScript 6

Érase una vez, la cosa más alucinante que podías poner en una web era algo de este estilo:

Historia

alert("Hola! Bienvenido a mi página web!");

Hoy

¿Qué es ECMA?

  • ECMA-6 – 7-bit Coded Character Set (based on  ASCII), also approved as ISO/IEC 646 [5]
  • ECMA-35 – Character Code Structure and Extension Techniques, also approved as ISO/IEC 2022 [6]
  • ECMA-48 – Control Functions for Coded Character Sets, also approved as ISO/IEC 6429 [7]
  • ECMA-119 –  CD-ROM volume and filestructure (later known as  ISO 9660) [8]
  • ECMA-130 –  CD-ROM "Yellow Book" format
  • ECMA-262 –  ECMAScript Language Specification (often referred to as JavaScript) [9]
  • ECMA-334 –  C# Language Specification [10]
  • ECMA-335 –  Common Language Infrastructure (CLI) [11]
  • ECMA-341 – Environmental design considerations for electronic products [12]
  • ECMA-363 –  Universal 3D File Format [13]
  • ECMA-367 – Eiffel: Analysis, design and programming Language (See  Eiffel programming language) [14]
  • ECMA-372 –  C++/CLI Language Specification [15]
  • ECMA-376 –  Office Open XML (later known as  ISO/IEC 29500)
  • ECMA-377 –  Holographic Versatile Disc (HVD) Recordable Cartridges [16]
  • ECMA-378 – Read-Only Memory Holographic Versatile Disc (HVD-ROM) [17]
  • ECMA-388 –  Open XML Paper Specification [18]
  • ECMA-402 –  ECMAScript Internationalization API Specification [19]
  • ECMA-404 –  JSON [20]
  • ECMA-408 –  Dart language specification [21]

¿Qué es ECMAScript?

  • ECMAScript es el nombre del estándar internacional que define JavaScript
  • Definido por un comité técnico (TC-39) de ecma international.
  • Identificado como Ecma-262 y ISO/IEC 16262
  • No es parte del W3C

Historia de ECMAScript

1994

  • Mocha/LiveScript liberado en Netscape Navigator
  • Al poco tiempo, renombrado como JavaScript
  • Netscape Enterprise Server permite ejecutar JS en lado de servidor

1996

  • Oracle registra la marca "JavaScript"
  • JavaScript aparece en Internet Explorer 3.0
  • IIS también comienza a soportar JavaScript en el lado del servidor

1997

  • Primera edición de ECMA 262-1 (ECMAScript 1)
  • Microsoft renombra su JavaScript a JScript
  • Se soluciona el bug del "efecto 2000" en los métodos Date()

2000

  • ECMAScript 262-3 publicado

Historia de ECMAScript

2005

  • Se decide no publicar ECMAScript 4, también conocido como Harmony

2009

  • Se publica ECMAScript 5
  • Aparece NodeJS

2015

  • Se publica ECMAScript 6, tras años de retrasos y cambios de nombre. Estaba pensado para 2013.
  • Se decide renombrar la versión a ECMAScript 2015 para liberar una actualización anual

TC39

  • Comité de 39 expertos que contribuyen debaten propuestas para incorporar al estándar
  • Publican su trabajo en GitHub
Stage Purpose
0 (Strawman) Permite incorporar la propuesta a la especificación
1 (Proposal) Se describe la necesidad de la funcionalidad y se describe la solución, así como futuros cambios
2 (Draft) Se describe la sintaxis y semática utilizando formal
3 (Candidate) Se recoge feedback de implementaciones y usuarios
4 (Finished) Indica que la funcionalidad está lista para entrar en la especificación formal del estándar

¿Puedo usar ECMAScript 2015 hoy?

Absolutamente, sí.

  • En Node.JS, está soportado desde la versión 4.0.0
  • En Chrome, al usar el mismo motor V8 que Node.JS
  • En el resto de navegadores, gracias a herramientas como Babel.
  • Tabla de compatibilidad de navegadores

Instalación y uso de Babel

¿Qué es Babel?

  • Es un compilador de JavaScript.
  • Aplica transformaciones a código escrito utilizando sintaxis de ECMAScript 2015 o JSX.
  • Nos sirve para escribir ECMAScript 2015 hoy sin preocuparnos por el soporte de navegadores

 

myJavascript("foobar");
myNewTransformedJavaScript("yay!");

Escribes tu JavaScript

Babel lo transforma

¿Cómo funciona?

babel-cli

  • Package que instala la herramienta de interfaz de línea de comandos
  • Permite ejecutar babel en terminal, o como tarea de npm
npm i --save-dev babel-cli

babel-plugin

  • Cada transformación que puede realizar Babel se publica independientemente como un plugin
  • Ejemplos:
    • es2015-arrow-functions
    • es2015-block-scoped-functions
    • es2015-block-scoping
    • es2015-classes
    • ... etc

babel-preset

  • Un preset de Babel es un conjunto de plugins.
  • Existen algunos ya creados, pero podemos crear nuestros propios presets
  • Se configuran en un fichero .babelrc
{
    "presets": [ "es2015" ],
    "plugins": []
}

babel-core

  • Contiene la API para utilizar Babel de forma programática en NodeJS
import babel from 'babel-core';

const code = `class Example {}`;
const result = babel.transform(code, { /* options */ });

result.code; // Generated code
result.map; // Sourcemap
result.ast; // AST

babel-register

Sobreescribe la función  require() de Node.JS y realiza las transformaciones de dependencias al vuelo

require("babel-register");

Todos los archivos requeridos  por Node.JS  a partir de esta línea con extensión .es6, .es, .jsx y .js serán transformados por Babel.

babel-polyfill

  • Permite emular todo un entorno de ECMAScript 2015
  • Se utiliza añadiendo la siguiente dependencia de módulo en nuestra aplicación:
require("babel-polyfill");

// O bien

import 'babel-polyfill';
  • Para utilizarlo en browsers, tendremos que utilizar un sistema de empaquetado como Webpack o Browserify para asegurar que el módulo se carga en browser

Demo: Instalación, configuración y uso de Babel

Variables de ámbito de bloque

Template strings

let holaMundo = `Hola, mundo!`;

Sintaxis

const lorem = `Lorem ipsum dolor sit amet,
consectetur adipisicing elit,
sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua.`;

Múltiples líneas

const COLOR = 'blue';

const CAPTAIN_OBVIOUS = `The heaven is ${COLOR}`;

Interpolación

const tag = function(strings, args){
    ...
};

const NAME = 'Dani';

tag`Hola ${NAME}`;

Función de etiquetado

const raw = function(strings, args) {
  return strings.raw[0];
}
console.log(raw`Hello!\n`); // Hello!\n

raw

Desestructuración

Sintaxis

const numbers = ['1', '2', '3'];

const [uno, dos, tres] = numbers;

Sintaxis

let object = { one: 1, two: 2 };

let {one, two} = object;

Parámetros por defecto

Sintaxis

function sayHello({
    name = 'Joan', 
    surname = 'Leon'
  } = {}) {
    console.log('Hello', name, surname);
};

sayHello();

Spread operator

Sintaxis

const values = [1, 2, 3, 4];

console.log(values); // [1, 2, 3, 4]
console.log(...values); // 1 2 3 4

Arrow functions y ámbito léxico

Sintaxis

const echo = text => text;
console.log(echo('Hello, arrow functions!'));

Sintaxis

const echo = function(text) {
    return text;
};

console.log(echo('Bye, non-arrow functions!'));

Clases

Sintaxis

class Sample {
  constructor(value) {
    this.value = value;
  }
  static staticMethod() {
    return 'Soy un método estático';
  }
  prototypeMethod() {
    return 'Soy un método de prototipo';
  }
}

Object literals

Nueva sintaxis para métodos

const myES6Object = {
  foo(){
    // ...
  },
  bar(x, y){
    // ...
  }
}

Propiedades computadas

const propertyKey = 'foo';
const something = 'ar';
const object = {
    [propertyKey]: true,
    [`b${something}`]: 123
};

Nombres de métodos computados

const methodKey = 'greeting';
const yetAnotherObject = {
  [methodKey]() {
    return 'Hello!';
  }
};

Iteradores + for...of

for...of

var numbers = [1, 2, 3, 4];

for(const number of numbers){
  console.log(number);
}

Protocolo iterable

Un objeto será iterable si implementa una propiedad mediante el símbolo:

[Symbol.iterator]

Generadores

Módulos

Map, Weakmap, Set, WeakSet

Promises

Concepto

let promise = readFile('data.txt');

Ciclo de vida

  • Fulfilled - la operación asíncrona de la promesa se ha completado con éxito
  • Rejected - la operación asíncrona no se ha completado con éxito, ya sea por un error o por otra causa

Ciclo de vida

Declaración

const doPromise = () => {
  return new Promise((resolve, reject) => {
    // Do something
    if(error){
      reject(error);
    }
    // If succeeds
    resolve(result);
  });
};

Uso

let promiseResult = doPromise();

promise.then((result) => {
  // fullfillment
}).catch((err) => {
  // rejection
});

Symbols

¿Qué es un símbolo?

Un símbolo es un tipo de datos cuyos valores son únicos e inmutables.

Dichos valores pueden ser utilizados como identificadores de las propiedades de los objetos

let mySymbol = new Symbol('mySymbol');

Proxies

Sintaxis

var target = { /* propiedades y métodos */ };
var handler = { /* funciones capturadoras */ };
 
var proxy = new Proxy(target, handler);

La API Proxy define un constructor de proxies al que se le pasa como primer argumento el objeto que se va a capturar (llamado target) y como segundo argumento el handler que realizará la captura. Ejemplo:

Configuración básica

const target = {};
const handler = {
    get(target, propKey, receiver) {
        console.log(`get ${propKey}`);
        return 'hello';
    }
}

const proxy = new Proxy(target, handler);

console.log(proxy.foo); 
// get foo
// hello

Uso con Babel

  • Muy experiemental, difícil transpilado a ES5, por lo que no hay polyfills
  • Soportado de forma nativa en las últimas versiones de Chrome
  • Package npm harmony-reflect

Para qué sirve

Los proxies de ES2015 proporcionan una API para capturar o interceptar cualquier operación realizada sobre un objeto y para modificar cómo se comporta ese objeto. Los proxies de JavaScript son útiles para muchas cosas, como por ejemplo:

  • Intercepción.
  • Virtualización de objetos.
  • Gestión de recursos.
  • Hacer profiling y generar logs durante la depuración de una aplicación.
  • Seguridad y control de acceso.
  • Definición de "contratos" al usar objetos.
var validator = {
  set: function(obj, prop, value) {
    if (prop === 'yearOfBirth') {
      if (!Number.isInteger(value)) {
        throw new TypeError('yearOfBirth no es un número entero');
      }
 
      if (value > 3000) {
        throw new RangeError('yearOfBirth no parece válido');
      }
    }
 
    // operación original para guardar el valor en la propiedad
    obj[prop] = value;
  }
};
 
var person = new Proxy({}, validator);
 
person.yearOfBirth = 1986;
console.log(person.yearOfBirth); // 1986
person.yearOfBirth = 'eighties'; // lanza una excepción
person.yearOfBirth = 3030;       // lanza una excepción

Ejemplo: Validación

Reflection

Objeto global que proporciona funciones estáticas capaces de intereceptar operaciones de JavaScript

La mayoría de sus métodos estáticos tienen una equivalencia en el objeto Object o Function

Las ventajas que ofrece el uso de Reflect son:

  • Aplicación de funciones más fiable
  • Valores de retorno más útiles
  • Sintaxis menos verbosa

Reflect global object

Reflect.apply

Reflect.apply(target, thisArgument, argumentsList)

// ES5
Function.prototype.apply.call(Math.floor, undefined, [1.75]);

// ES2015
Reflect.apply(Math.floor, undefined, [1.75]); // 1;

Reflect.defineProperty

Reflect.defineProperty(target, propertyKey, attributes)

if (Reflect.defineProperty(target, property, attributes)) {
  // success
} else {
  // failure
}

Reflect.deleteProperty

Reflect.deleteProperty(target, propertyKey)

var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }

Más ejemplos de Reflect

Decoradores

Decorators

  • Propuesta para ES2016
  • Es una expresión
  • Evalúa una función
  • Toma el targetname y el descriptor del decorador como argumentos
  • Opcionalmente retorna un descriptor de decorador para instalar en el objeto target

Ejemplo

class Person {
  @readonly
  name() { return `${this.first} ${this.last}` }
}
const readonly = (target, name, descriptor) => {
    // ...
}

Parámetros de un decorador

  • Target: El objeto al que queremos modificar su definición de propiedades
  • Name: El nombre de la propiedad a modificar
  • Descriptor: La descripción de la propiedad del objeto, que a su vez es:
    • configurable: indica si puede ser modificada
    • enumerable: se puede usar con un "for...of"
    • value: valor asociado a la propiedad
    • writable: indica si la propiedad puede ser cambiada con una asignación
    • get: indica si la propiedad es un getter
    • set: indica si la propiedad es un setter

Decorador readonly

const readonly = (target, name, descriptor) => {
    descriptor.writable = false;
    return descriptor;
}

Uso con Babel

  • Especificación en Stage-1, por lo que puede cambiar en un futuro
  • En Babel 6 no se ha querido implementar, a la espera de una mayor madurez de la propuesta
  • Para usarlo, necesitamos el plugin babel-plugin-transform-decorators-legacy

Resources

Aprende ECMAScript 2015

By Daniel de la Cruz Calvo

Aprende ECMAScript 2015

Aprende ECMAScript 2015 (ES6), el último estándar del lenguaje JavaScript

  • 1,657