¡Consejos y trucos de ES6 para hacer que su código sea más limpio, más corto y más fácil de leer!

Literales de plantilla

Los literales de plantilla hacen que trabajar con cadenas sea mucho más fácil que antes. Comienzan con un tic de retroceso y pueden insertar variables usando $ {variable}. Compare estas dos líneas de código:

var fName = 'Peter', sName = 'Smith', edad = 43, trabajo = 'fotógrafo';
var a = 'Hola, I \' m '+ fName +' '+ sName +', I \ 'm' + age + 'y trabajo como' + job + '.';
var b = `Hola, soy $ {fName} $ {sName}, soy $ {age} y trabajo como $ {job} .`;

Esto hace la vida mucho más simple y el código más fácil de leer. Puede poner cualquier cosa dentro de las llaves: variables, ecuaciones o llamadas a funciones. Los usaré en ejemplos a lo largo de este artículo.

Alcance del bloque de sintaxis

JavaScript siempre ha sido definido por funciones, por lo que se ha vuelto común envolver todo un archivo JavaScript en una expresión de función invocada inmediatamente (IIFE) vacía. Esto se hace para aislar todas las variables en el archivo, para que no haya conflictos de variables.

Ahora, tenemos un alcance de bloque y dos nuevas declaraciones de variables que están vinculadas a un bloque.

Declaración de "Let"

Esto es similar a var pero tiene algunas diferencias notables. Debido a que tiene un alcance de bloque, se puede declarar una nueva variable con el mismo nombre sin afectar las variables externas.

var a = 'auto';
{
    dejar a = 5;
    console.log (a) // 5
}
console.log (a) // auto

Debido a que está vinculado a un alcance de bloque, resuelve esta clásica pregunta de entrevista:
"¿Qué es la salida y cómo lo haría funcionar como espera?"

para (var i = 1; i <5; i ++) {
    setTimeout (() => {console.log (i);}, 1000);
}

En este caso, genera "5 5 5 5 5" porque la variable i cambia en cada iteración.

Si cambia la var para let, entonces todo cambia. Ahora, cada ciclo crea un nuevo alcance de bloque con el valor de i enlazado a ese ciclo. Es a pesar de que has escrito:

{let i = 1; setTimeout (() => {console.log (i)}, 1000)}
{let i = 2; setTimeout (() => {console.log (i)}, 1000)}
{let i = 3; setTimeout (() => {console.log (i)}, 1000)}
{let i = 4; setTimeout (() => {console.log (i)}, 1000)}
{let i = 5; setTimeout (() => {console.log (i)}, 1000)}

Otra diferencia entre var y let es que let no se eleva como var.

{
    console.log (a); // indefinido
    console.log (b); // ReferenceError
    var a = 'auto';
    dejar b = 5;
}

Debido a su alcance más estricto y su comportamiento más predecible, algunas personas han dicho que debe usar let en lugar de var, excepto donde específicamente necesita el levantamiento o un alcance más flexible de la declaración var.

Const

Si antes deseaba declarar una variable constante en JavaScript, era una convención nombrar la variable en mayúsculas. Sin embargo, esto no aseguraría la variable, solo les informaría a otros desarrolladores que era una constante y que no debería cambiarse.

Ahora tenemos la declaración const.

{
    const c = "árbol";
    console.log (c); // árbol
    c = 46; // ¡Error de tecleado!
}

const no hace que la variable sea inmutable, solo bloquea su asignación. Si tiene una asignación compleja (objeto o matriz), el valor aún puede modificarse.

{
    const d = [1, 2, 3, 4];
    const dave = {nombre: 'David Jones', edad: 32};
    d.push (5);
    dave.job = "vendedor";
    console.log (d); // [1, 2, 3, 4, 5]
    console.log (dave); // {edad: 32, trabajo: "vendedor", nombre: 'David Jones'}
}

Problema con funciones de alcance de bloque

Las declaraciones de funciones ahora se especifican para estar vinculadas al ámbito de bloqueo.

{
    bar(); // trabajos
    barra de funciones () {/ * hacer algo * /}
}
bar(); // no funciona

El problema surge cuando declara una función dentro de una instrucción if.

Considera esto:

si algo) {
    function baz () {console.log ('Pasé')}
} más {
    function baz () {console.log ('No lo pasé')}
}
baz ();

Antes de ES6, ambas declaraciones de funciones se habrían izado y el resultado habría sido 'No pasé' sin importar lo que fuera.
Ahora obtenemos 'ReferenceError', ya que baz siempre está vinculado por el alcance del bloque.

Untado

ES6 presenta el operador ..., que se conoce como el "operador de propagación". Tiene dos usos principales: distribuir una matriz u objeto en una nueva matriz u objeto, y unir múltiples parámetros en una matriz.

El primer caso de uso es el que probablemente encontrará más, así que lo veremos primero.

dejar a = [3, 4, 5];
sea ​​b = [1, 2, ... a, 6];
console.log (b); // [1, 2, 3, 4, 5, 6]

Esto puede ser muy útil para pasar un conjunto de variables a una función desde una matriz.

function foo (a, b, c) {console.log (`a = $ {a}, b = $ {b}, c = $ {c}`)}
dejar datos = [5, 15, 2];
foo (... datos); // a = 5, b = 15, c = 2

Un objeto también se puede extender, ingresando cada uno de los pares de valores clave en el nuevo objeto. (La distribución de objetos está en la etapa 4 de la propuesta y será oficialmente en ES2018. Solo es compatible con Chrome 60 o posterior, Firefox 55 o posterior y Nodo 6.4.0 o posterior)

let car = {type: 'vehículo', ruedas: 4};
let fordGt = {make: 'Ford', ... car, model: 'GT'};
console.log (fordGt); // {marca: 'Ford', modelo: 'GT', tipo: 'vehículo', ruedas: 4}

Otra característica del operador de propagación es que crea una nueva matriz u objeto. El siguiente ejemplo crea una nueva matriz para b, pero c solo se refiere a la misma matriz.

dejar a = [1, 2, 3];
let b = [... a];
dejar que c = a;
b.push (4);
console.log (a); // [1, 2, 3]
console.log (b); // [1, 2, 3, 4] haciendo referencia a diferentes matrices
c.push (5);
console.log (a); // [1, 2, 3, 5]
console.log (c); // [1, 2, 3, 5] haciendo referencia a la misma matriz

El segundo caso de uso es reunir variables en una matriz. Esto es muy útil cuando no sabe cuántas variables se pasan a una función.

función foo (... args) {
    console.log (args);
}
foo ('carro', 54, 'árbol'); // ['auto', 54, 'árbol']

Parámetros predeterminados

Las funciones ahora se pueden definir con parámetros predeterminados. Los valores faltantes o indefinidos se inicializan con el valor predeterminado. Solo tenga cuidado, porque los valores nulos y falsos están obligados a 0.

función foo (a = 5, b = 10) {
    console.log (a + b);
}
foo (); // 15
foo (7, 12); // 19
foo (indefinido, 8); // 13
foo (8); // 18
foo (nulo); // 10 como nulo se obliga a 0

Los valores predeterminados pueden ser más que solo valores: también pueden ser expresiones o funciones.

función foo (a) {devuelve a * 4; }
barra de funciones (x = 2, y = x + 4, z = foo (x)) {
    console.log ([x, y, z]);
}
bar(); // [2, 6, 8]
barra (1, 2, 3); // [1, 2, 3]
barra (10, indefinida, 3); // [10, 14, 3]

Desestructuración

La desestructuración es el proceso de desmontar la matriz u objeto en el lado izquierdo del signo igual. La matriz u objeto puede provenir de una variable, función o ecuación.

sea ​​[a, b, c] = [6, 2, 9];
console.log (`a = $ {a}, b = $ {b}, c = $ {c}`); // a = 6, b = 2, c = 9
function foo () {return ['auto', 'perro', 6]; }
let [x, y, z] = foo ();
console.log (`x = $ {x}, y = $ {y}, z = $ {z}`); // x = coche, y = perro, z = 6

Con la desestructuración de objetos, las claves del objeto se pueden enumerar dentro de llaves para extraer ese par clave-valor.

barra de función () {return {a: 1, b: 2, c: 3}; }
let {a, c} = bar ();
console.log (a); // 1
console.log (c); // 3
console.log (b); // indefinido

A veces, desea extraer los valores pero asignarlos a una nueva variable. Esto se hace usando un emparejamiento 'clave: variable' a la izquierda del signo igual.

función baz () {
    regreso {
        x: 'auto',
        y: 'Londres',
        z: {nombre: 'John', edad: 21}
    };
}
let {x: vehículo, y: ciudad, z: {nombre: conductor}} = baz ();
console.log (
    `Voy a $ {city} con $ {driver} en su $ {vehicle} .`
); // Voy a Londres con John en su auto.

Otra cosa que permite la desestructuración de objetos es asignar un valor a múltiples variables.

let {x: primero, x: segundo} = {x: 4};
console.log (primero, segundo); // 4, 4

Literales de objetos y parámetros concisos

Cuando está creando un objeto literal a partir de variables, ES6 le permite omitir la clave si es el mismo que el nombre de la variable.

dejar a = 4, b = 7;
sea ​​c = {a: a, b: b};
dejar conciso = {a, b};
console.log (c, conciso) // {a: 4, b: 7}, {a: 4, b: 7}

Esto también se puede usar en combinación con la desestructuración para hacer que su código sea mucho más simple y limpio.

función foo () {
    regreso {
        nombre: 'Anna',
        edad: 56,
       trabajo: {empresa: 'Tesco', título: 'Gerente'}
    };
}
// pre ES6
deje a = foo (), name = a.name, age = a.age, company = a.job.company;
// ES6 desestructuración y parámetros concisos
let {nombre, edad, trabajo: {empresa}} = foo ();

También se puede usar para desestructurar objetos pasados ​​a funciones. Los métodos 1 y 2 son como lo habría hecho antes de ES6, y el método 3 utiliza parámetros concisos y de desestructuración.

dejar persona = {
    nombre: 'Anna',
    edad: 56,
    trabajo: {empresa: 'Tesco', título: 'Gerente'}
};
// Método 1
función old1 (persona) {
    var yearOfBirth = 2018 - person.age;
    console.log (`$ $ person.name} funciona en $ {person.job.company} y nació en $ {yearOfBirth} .`);
}
// método 2
función old1 (persona) {
    var age = person.age,
        yearOfBirth = 2018 - edad,
        nombre = persona.nombre,
        empresa = persona.job.company;
    console.log (`$ {name} funciona en $ {company} y nació en $ {yearOfBirth} .`);
}
// método 3
función es6 ({edad, nombre, trabajo: {empresa}}) {
    var yearOfBirth = 2018 - edad;
    console.log (`$ {name} funciona en $ {company} y nació en $ {yearOfBirth} .`);
}

Con ES6, podemos extraer la edad, el nombre y la empresa sin una declaración de variable adicional.

Nombres de propiedades dinámicas

ES6 agrega la capacidad de crear o agregar propiedades con claves asignadas dinámicamente.

let city = 'sheffield_';
dejar a = {
    [ciudad + 'población']: 350000
};
a [city + 'county'] = 'South Yorkshire';
console.log (a); // {sheffield_population: 350000, sheffield_county: 'South Yorkshire'}

Funciones de flecha

Las funciones de flecha tienen dos aspectos principales: su estructura y su enlace.

Pueden tener una estructura mucho más simple que las funciones tradicionales porque no necesitan la palabra clave de función y automáticamente devuelven lo que está después de la flecha.

var foo = función (a, b) {
    devuelve a * b;
}
let bar = (a, b) => a * b;

Si la función requiere más que un simple cálculo, se pueden usar llaves y la función devuelve lo que sea devuelto desde el alcance del bloque.

dejar baz = (c, d) => {
    let length = c.length + d.toString (). length;
    dejemos e = c. unirse (',');
    devuelve `$ {e} y hay una longitud total de $ {length}`;
}

Uno de los lugares más útiles para las funciones de flecha es en funciones de matriz como .map, .forEach o .sort.

let arr = [5, 6, 7, 8, 'a'];
let b = arr.map (item => item + 3);
console.log (b); // [8, 9, 10, 11, 'a3']

Además de tener una sintaxis más corta, también soluciona los problemas que a menudo surgían en torno a este comportamiento vinculante. La solución con las funciones anteriores a ES6 era almacenar esta referencia, a menudo como una variable propia.

var clickController = {
    doSomething: function (..) {
        var self = esto;
        btn.addEventListener (
            'hacer clic',
            function () {self.doSomething (..)},
            falso
       );
   }
};

Esto tuvo que hacerse porque este enlace es dinámico. Esto significa que el this dentro del detector de eventos y el this dentro del doSomething no se refieren a lo mismo.

Dentro de las funciones de flecha, este enlace es léxico, no dinámico. Esta fue la principal característica de diseño de la función de flecha.

Si bien este enlace léxico puede ser excelente, a veces eso no es lo que se desea.

dejar a = {
    oneThing: (a) => {
         dejar b = a * 2;
         this.otherThing (b);
    },
    otherThing: (b) => {....}
};
a.oneThing (6);

Cuando usamos a.oneThing (6), la referencia this.otherThing (b) falla ya que esto no apunta al objeto, sino al alcance circundante. Si está reescribiendo código heredado utilizando la sintaxis ES6, esto es algo a tener en cuenta.

para ... de Loops

ES6 agrega una forma de iterar sobre cada uno de los valores de una matriz. Esto es diferente del ciclo for ... in existente que recorre la clave / índice.

let a = ['a', 'b', 'c', 'd'];
// ES6
para (var val de a) {
    console.log (val);
} // "a B C D"
// pre-ES6
para (var idx en a) {
    console.log (idx);
} // 0 1 2 3

Usando el nuevo for ... of loop guarda agregando let let = a [idx] dentro de cada ciclo.

Las matrices, cadenas, generadores y colecciones son iterables en JavaScript estándar. Los objetos simples normalmente no se pueden repetir, a menos que haya definido un iterador para ello.

Numerales Literales

El código ES5 manejó bien los formatos de números decimales y hexadecimales, pero no se especificó la forma octal. De hecho, se rechazó activamente en modo estricto.

ES6 ha agregado un nuevo formato, agregando una o después del 0 inicial para declarar el número como octal. También han agregado un formato binario.

Número (29) // 29
Número (035) // 35 en forma octal antigua.
Número (0o35) // 29 en nueva forma octal
Número (0x1d) // 29 en hexadecimal
Número (0b11101) // 29 en forma binaria

Y mucho más…

Hay mucho, mucho más que ES6 nos ofrece para hacer que nuestro código sea más limpio, más corto, más fácil de leer y más robusto. Mi objetivo es escribir una continuación de este artículo que abarque los bits menos conocidos de ES6.

Si no puede esperar tanto, lea el libro de Jyle You Don't Know Know JS de Kyle Simpson en ES6, ¡o visite este pequeño y brillante sitio web!

¿Quieres convertirte en desarrollador y obtener tu primer trabajo de software? Descargue los 7 pasos para convertirse en desarrollador y obtener su primer trabajo.

SIGUIENTE -> Cómo asegurar el trabajo de tus sueños. Domine el proceso de la entrevista Si le gustó esto y lo encontró útil, muestre su apoyo aplaudiendo y suscríbase para obtener más artículos como este.