Comenzando con ES6

ES6 se refiere a la versión 6 del estándar ECMAScript la cual fue publicada en junio de 2015 bajo el nombre de ECMAScript2015, actualmente no está completamente implementada por los navegadores, siendo la versión 5 la más común.

En mi experiencia como desarrollador siempre he estado en contacto con JavaScript y los retos que esto conlleva, por ejemplo, variables que se definen de forma global causando resultados inesperados como valores sobrescritos en bloques de código que no deberían ser afectados entre otras malas prácticas, con el tiempo el lenguaje ha ido evolucionando agregando nuevas mejoras al lenguaje. La versión ES6 nos trae mejoras como el uso de constantes, la definición de variables a nivel de bloque, poder asignar un valor default a los parámetros, entre muchas más.

Desafortunadamente como ya lo mencione no todos los navegadores soportan estas nuevas características, en este link puedes encontrar la lista de compatibilidad en diferentes navegadores. Sin embargo podemos hacer uso de ellas a través de herramientas llamadas “Transpiladores” que transforman el código a su versión equivalente en ES5, siendo la más común Babel.js.

Ahora revisemos algunas de las nuevas características que se incluyen en ES6:

Let

Nos permite declarar variables a nivel de bloque y solo será visible dentro de él, a diferencia de var que define variables a nivel global o de función. Veamos las diferencias:

function myFunction(flag) {
  if(flag) {
    var x = 3;
  }
  return x;
};

myFunction(false) // undefined

En este ejemplo nuestra función nos regresa undefined debido a la naturaleza de var que las variables son declaradas a nivel de la función sin importar si esta está dentro del bloque if, es decir a pesar de que explícitamente declaramos la variable x dentro del bloque if JavaScript lo que hace es buscar la declaracion de variables y moverlas al nivel más alto, en este caso la función myFunction, sería equivalente a lo siguiente:

function myFunction(flag) {
  var x;
  if(flag) {
    x = 3;
  }
  return x;
};

myFunction(false) // undefined

Con el uso de let tendremos un resultado totalmente diferente:

function myFunction(flag) {
  if(flag) {
    let x = 3;
  }
  return x;
};

myFunction(false) //Uncaught ReferenceError: x is not defined

Esto debido que x solo existen dentro del bloque if.

Const

Al igual que let nos permite declarar variables a nivel de bloque, pero con la peculiaridad de que son variable de solo lectura, es decir una vez que se asigna el valor este no puede ser cambiado, veamos un ejemplo:

function AreaOfCircle(radius) {
  const pi = 3.1415926535;
  pi = 3.1416;
  
  return pi * (radius * radius);
}

AreaOfCircle(20); // Uncaught TypeError: Assignment to constant variable.

Cuando declaramos constantes usando const estas existen a nivel del bloque, si sobrescribimos la referencia con otro valor como en el siguiente ejemplo, el valor del área del circulo sería diferente ya que hace referencia al valor dentro de nuestra función AreaOfCircle y no a la que fue declarada fuera del bloque:

const pi = 3.1415926535;

function AreaOfCircle(radius) {
  var pi = 3.1416;
  
  return pi * (radius * radius);
}

AreaOfCircle(20); //1256.6399999999999
console.log(pi); //3.1415926535

Destructuring

Destructuring nos permite "desempaquetar" un array o un objeto en diferentes variables en una sola operación, veamos un ejemplo

persona = {
  nombre: "Fernando",
  apellido: "Barajas",
  edad: 39
}

function saludos(persona) {
  let { nombre, apellido, edad } = persona;
  
  console.log(`Hola mi nombre es ${nombre} ${apellido}, tengo ${edad} años `);
}

saludos(persona) //Hola mi nombre es Fernando Barajas, tengo 39 años

Como podrás observar en la primer linea dentro de la función saludos hacemos uso de esta mejora, es decir, desestructurando el valor del objeto persona y asignando a las variables name, apellido y edad sus valores respectivamente.

Debemos tener cuidado con los nombres de las llaves en el objeto, ya que al usar destructuring deben existir una coincidencia entre el nombre de la variable y la propiedad en el objeto, en caso contrario esta no va a tomar valor alguno, tampoco nos arrojaría algún error, sino que simplemente asignaría undefined a la variable.

Template Literals

Talvez te diste cuenta en nuestro ejemplo de Destructuring que usamos una forma diferente para construir el mensaje de saludo dentro del console.log, a esta sintaxis se le llama interpolación, y nos evitar el tener que usar el operador + para concatenar dos o más cadenas.

Para usar esta nueva funcionalidad solo debemos encerrar nuestro string con el caracter "`" en lugar de las comillas y usar los operadores %{} para pasar una variable, una expresión o una función:

var a = 5;
var b = 10;
console.log(`Fifteen is ${a + b} and
not ${2 * a + b}.`); // Fifteen is 15 and
                     // not 20.
function AreaOfCircle(radius) {
  const pi = 3.1415926535;
  
  return pi * (radius * radius);
}

function toStringAreaOfCircle(strings, radius) {
  const area = AreaOfCircle(radius);
  
  return `${strings[0]}${radius},${strings[1]}${area}`
}

let areaDeCirculo = toStringAreaOfCircle`El area de un circulo de radio ${20} es de`
console.log(areaDeCirculo);
//El area de un circulo de radio 20, es de 1256.6370614

Spread Operator

Te permite obtener los elementos dentro de un objeto iterable como son los arrays. Por ejemplo:

  let rubyc = "RUBYC";
  let caracteres = [...rubyc];
  console.log(caracteres) //["R", "U", "B", "Y", "C"];
  
  let topScores = [99, 76, 80, 97, 30];
  Math.max(...topScores); //99
  
  let datos = { nombre: "Fernando", apellido: "Barajas" };
  let persona = {...datos, edad: 39 };
  console.log(persona); //{nombre: "Fernando", apellido: "Barajas", edad: 39}

Como podrás observar la forma de usar este operador es anteponiendo ... a la referencia de la variable que contiene el objeto iterable, expandiendo sus propiedades al nivel del nuevo objeto por construir, esto se le conoce como desestructuración de parámetros como ya vimos en las secciones anteriores.

Class

En esta version de ECMAScript se introduce el uso de clases, las cuales son "funciones especiales" que nos permiten hacer uso de las ventajas que nos da la programación orientada a objetos, como lo es:

  • Reusar código usando herencia (por prototipos), para más información podemos consultar este excelente post Trabajando con objetos en JavaScript.
  • Encapsulación de métodos y atributos.
  • Exponer los atributos para lectura y escritura.

Veamos un ejemplo:

class Persona {
  constructor(nombre, apellido, edad) {
    this.nombre = nombre;
    this.apellido = apellido;
    this.edad = edad;
  }
  
  toString() {
    return `Nombre completo: ${this.nombre} ${this.apellido}, Edad: ${this.edad}`
  }
}

let persona = new Persona("Fernando", "Barajas", 39);
console.log(persona.toString()); //Nombre completo: Fernando Barajas, Edad: 39

Modules and Import

También se estandarizó una forma de encapsular lógica por módulos en archivos aislados para ser reusada en otros módulos, utilizando la palabra reservada import al inicio del archivo podemos incluir nuestro modulo, por ejemplo, podríamos tener un archivo llamado operaciones.js en el cual encapsulamos funciones para sumar, restar, multiplicar y dividir y hacer referencia desde otro archivo incluyendo estas operaciones; solo basta con agregar la línea de código import * from 'operaciones.js'; para tener acceso a los métodos.

// operaciones.js

function sum(...args) {
  return args.reduce((num, tot) => tot + num);
}

function mult(...args) {
  return args.reduce((num, tot) => tot * num);
}

function resta(...args) {
 return args.reduce((num, tot) => tot - num);
}

function division(dividendo, divisor) {
  return dividendo/divisor;
}

export { sum, mult, resta, division };

y en nuestro archivo main.js

// main.js
import * from './operaciones.js';

console.log( sum(1,2,3,4) ); // 10

Arrow Functions

También conocidas como Fat Arrow Functions, son una forma más concisa de escribir funciones, utilizan el token => el cual asemeja una flecha. Cabe mencionar que son funciones similares a las creadas con la palabra function pero sin contexto.

La peculiaridad de una Arrow Funtion es la forma de como de define el valor de this dentro de la función, la cual es de manera léxica, es decir que el valor lo toma del contexto más cercano y va a ser externo a él si no existe alguno, el contexto siempre será el objeto global window, en el caso de funciones constructoras las arrow function's se ligan por defecto al contexto de la función constructora, Veamos un ejemplo:

function Persona() {
  this.edad = 39;
  // this hace referencia al contexto Persona

  setInterval(() => {
    this.edad ++; // El valor es obtenido del Contexto Persona
  }, 1000)
}

let p = new Persona();
const array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];

let numerosPar = array.filter(numero => numero % 2 === 0);
console.log(numerosPar); // [2, 4, 6, 8, 10, 12, 14, 16]

Como podrás darte cuenta esta versión de ECMAScript se enfoca mucho en la sintaxis, haciendo más legible nuestro código y arregla muchas deficiencias que el lenguaje tenía como la forma de crear clases y su herencia ahora es más parecida a como la usaríamos en otros lenguajes, espero esta introducción a las mejoras en ES6 te sean de ayuda cuando te encuentres con código de JavaScript en su nuevo formato, sin olvidar que como desarrollador de Ruby eventualmente tendrás que trabajar con JavaScript y debes saber cómo funciona especialmente esta versión que revoluciono como escribimos JavaScript.




comments powered by Disqus

Siguenos

Boletí de noticias