ECMAScript 2015
Uso
1. Compatibilidad
ECMAScript 2015 anteriormente llamado ECMAScript 6, está disponible con todos los navegadores recientes: Chrome, Firefox, Edge, Safari, Opera. Por otro lado, no está disponible en Internet Explorer (antepasado de Edge), pero la penetración en el mercado de este navegador, está disminuyendo de manera constante a menos del 2 % en la actualidad. También se tiene muy en cuenta en el móvil.
Por lo tanto, ahora es posible utilizar ECMAScript 2015 en sitios web para el gran público en general. Para seguir siendo compatible con los navegadores antiguos, es posible configurar una librería de JavaScript con menos funciones, sin obstaculizar el funcionamiento del sitio web. Para hacer esto, se probará la versión del navegador tan pronto como se cargue la página. Posteriormente se tendrá en cuenta la librería correcta según el resultado.
La primera librería ofrecerá un servicio mínimo para que el sitio funcione con Internet Explorer.
// jib.js
document.body.onload = function() { alert( "Versión simple" ); };
La segunda librería ofrecerá el servicio completo para todos los navegadores compatibles 2015.
// lib2015.js
document.body.onload = function() { alert( "Versión óptima" ); };
Solo resta detectar el navegador actual con ayuda de la propiedad window.navigator.userAgent y cargar el script correcto en consecuencia.
<!DOCTYPE html>
<html>
<head>
<script>
var ua = window.navigator.userAgent;
var lib = "lib2015.js";
if ( ua.indexOf( "MSIE" ) > 0 || ua.indexOf( "Trident" ) > 0 ) {
// Detección Internet explorer ...
Estructura de datos más eficaz
1. Cadenas de caracteres
Hay nuevos tratamientos disponibles en las cadenas de caracteres:
-
repeat para duplicar una cadena.
-
startsWith para indicar si une cadena empieza por un valor.
-
endsWith para indicar si una cadena termina con un valor.
-
includes para saber si una cadena contiene otra cadena.
alert( "hola".repeat( 2 ) ); // « holahola »
alert( "hola".startsWith( "ho" ) ); // verdadero
alert( "hola".endsWith( "la" ) ); // verdadero
alert( "hola".includes( "ol" ) ); // verdadero
Es posible definir una cadena en varias líneas con posibles parámetros, delimitándola con el carácter `. Los parámetros están definidos por la sintaxis ${valor}.
let coche = { marca : "renault", modelo : "clio" };
let msg = `Es propietario de un coche
de marca ${coche.marca} y modelo ${coche.modelo}`;
alert( msg );
2. Colecciones
Es posible almacenar un conjunto de valores únicos gracias a la clase Set. Entre los principales métodos, tendremos:
-
add para agregar un valor.
-
delete para borrar un valor.
-
has para comprobar si existe un valor.
-
size para conocer el tamaño de la colección.
-
values es un iterador para recorrer el conjunto de valores. Asimismo, se utiliza...
Desarrollo orientado a objetos rápido
1. Clases
Como hemos visto hasta ahora, JavaScript no es completamente un lenguaje orientado a objetos, porque todo se basa en una propiedad prototype para compartir las mismas funciones entre diferentes objetos de una clase. También hemos visto que una función tiene un rol ambiguo al servir como función para algún procesamiento, pero también como constructor de clases.
ECMAScript 2015 hace tabla rasa de este sistema para convertirse en un verdadero lenguaje orientado a objetos. En este ejemplo, tenemos una clase Persona con un constructor (constructor), que recibe como argumentos un nombre y un apellido.
class Persona {
constructor( nombre, apellido ) {
this.nombre = nombre;
this.apellido = apellido;
}
hello() {
alert( "Hola " + this.nombre + " " + this.apellido );
}
}
La creación de una instancia y su uso no cambian. Por lo tanto, es perfectamente posible tener una librería de clases específica para ECMAScript 2015 y otra compatible con navegadores antiguos, sin cambiar el código principal.
let p = new Persona( "alexandre", "brillant" );
p.hello(); // Hola alexandre brillant
No es posible utilizar una interfaz de objeto en ECMAScript 2015. Cada invocación de un atributo o de una función de clase, debe estar precedida por this.
2. Herencia
La herencia con un posible padre se realiza mediante el uso de extends. La palabra clave super sirve para reutilizar los elementos de la clase padre durante una sobrecarga.
En nuestro ejemplo, vamos a empezar de nuevo desde la clase anterior que vamos a heredar, añadiendo un atributo puesto. Para invocar el código del constructor de la clase Persona, usamos super con los mismos argumentos.
class Empleado extends Persona {
constructor( nombre, apellido, puesto ) {
super( nombre, apellido );
this.puesto = puesto;
}
asignacion() {
alert( "Está asignado a " + this.puesto );
}
}
Tenga en cuenta que no es posible nombrar una función con el mismo nombre que un atributo.
Por lo tanto, durante su uso, podremos escribir:
let e = new Empleado(...
Programación modular simplificada
1. Exportación
Para construir un módulo, es suficiente con crear un archivo de script independiente. Para cada clase o función que desee que esté disponible, debe utilizar el prefijo export en la declaración.
En este ejemplo, hemos proporcionado un módulo vehiculos.js con una clase Vehiculo con una marca y un modelo como constructor.
export class Vehiculo {
constructor( marca, modelo ) {
this.marca = marca;
this.modelo = modelo;
}
}
También es posible definir la lista de las clases y funciones accesibles mediante la sintaxis: export { clase1, clase2..., funcion1... }.
El ejemplo anterior se podría haber escrito también de esta manera:
class Vehiculo {
constructor( marca, modelo ) {
this.marca = marca;
this.modelo = modelo;
}
}
export { Vehiculo }
2. Importación
Para importar un módulo, usaremos la palabra clave import. Solo se puede utilizar dentro de otro módulo. Hay dos formas de importar los elementos de un módulo. La primera consiste en obtener todos los elementos (clases/funciones) que son "exportables", gracias a un asterisco. En esta configuración debe tener un prefijo para cada módulo importado. Este...
Funciones simplificadas
1. Expresiones lambda
Las expresiones lambda facilitarán la escritura de funciones.
En el siguiente ejemplo, tenemos una función asociada con la variable t, declarada de la manera clásica.
let t = function test(a,b) { return a+b;}
alert( t(1,2) ); // « 3 »
Aquí, esta misma función se declara de forma simplificada. Los operandos y el resultado de la función están separados por =>.
let t2 = (a,b) => ( a+b );
alert( t(2,2) ); // «4»
Otro ejemplo, para recorrer una tabla usando la función forEach y construir rápidamente una nueva tabla con los valores inversos:
let a = [1,2,3,4,5];
let b = [];
a.forEach( v => b += -v );
console.log( b ); // -1 -2 -3 -4 -5
2. Iteradores
Los iteradores son funciones cuya única función es devolver una serie de valores. Evitan pasar por una tabla y se pueden usar directamente en un bucle. Se distinguen por un asterisco. La instrucción yield se utiliza para devolver cada valor.
let range = function* (min,max) {
while ( min <= max ) {
yield min++;
}
}
El iterador anterior representa todos los valores enteros entre dos límites. Si queremos usarlo en un bucle for, tenemos disponible la palabra clave of.
for ( let n of range(1,3) ) {
console.log( n ); // 1 2 3
}
El iterador se puede utilizar en una clase, usando un asterico como prefijo del nombre del iterador.
En el siguiente ejemplo, tenemos un iterador que nos permite recorrer más fácilmente por las diferentes marcas. La ventaja es que el iterador oculta la estructura de datos utilizada para almacenar estas marcas y así, evita cualquier error de manipulación que pueda corromper estos datos.
class Coches { ...
Desarrollo asíncrono
1. Simple
En el procesamiento asíncrono, el tratamiento está asociado con un evento particular que ocurrirá en el futuro. Por ejemplo, puede realizar el procesamiento después de un cierto período de tiempo o después de cargar un recurso. Por lo general, pasamos una función delegada que se activará cuando se produzca el evento.
Por ejemplo, si mostramos un mensaje después de tres segundos, podríamos escribir:
setTimeout( function() { alert( "Hola" ); }, 3000 );
Si luego tenemos que realizar otro procesamiento asincrónico, el código puede volverse complejo rápidamente, porque no estamos seguros de qué método se invoca y cuándo.
ECMAScript2015 estandariza la escritura de procesamientos asíncronos, gracias a la clase Promise. Esta clase tendrá como constructor la función a invocar durante el evento o bien una función que maneje la imposibilidad de tratar el evento.
Podríamos haber escrito el caso anterior de la siguiente manera:
let p = new Promise( ( hecho, error ) => (
setTimeout( () => hecho(), 3000 ) ) );
p.then( () => alert( "Hola") );
La ventaja es que todo nuestro tratamiento se puede administrar mediante el objeto p.
2. Múltiple
La clase Promise dispone de un método estático all, que recibe...
Facilitar el uso internacional
1. Números
La clase Intl tiene muchas traducciones en función de los países e idiomas, comenzando por el formateo de los números, con o sin separadores y teniendo en cuenta el separador decimal. El método estático NumberFormat permite formatear los números para una localización definida por el estándar IETF BCP 47. De forma simplificada, tendremos un código para representar el idioma y un código para representar el país.
let esNum = new Intl.NumberFormat( "es-ES" ); // formato español
let usNum = new Intl.NumberFormat( "en-US" ); // formato americano
let numero = 3141567.314;
alert( "formato en español = " + esNum.format( numero ) );
alert( "formato en inglés/us = " + usNum.format( numero ) );
NumberFormat sin argumento utiliza la localización por defecto.
2. Monedas
Para formatear una suma de dinero, también usaremos NumberFormat pero con un argumento adicional. Será un objeto especificando que se trata de una moneda y le indicaremos la moneda mediante un código de tres letras.
esNum = new Intl.NumberFormat( "es-ES", { style : "currency",
currency : "EUR" } );
alert( "Billete de " + esNum.format( 20 ) ); // «Billete de 20,00 €
3. Fechas/horas
El método estático...