La siguiente es una publicación invitada de Ryan Christiani. Ryan es profesor en HackerYou y ha estado trabajando en una serie de videos llamada Let’s Learn ES6. Se ofreció a juntar algo de eso en un formato de tutorial, que pensé que era perfecto ya que no hemos cubierto mucho ES2015 aquí en CSS-Tricks.
¿Lo que hay en un nombre?
En junio de 2015, se finalizó la mayor incorporación al lenguaje JavaScript. El nombre oficial es ECMAScript 2015, a veces denominado “ES6”, o ahora más comúnmente conocido como “ES2105”. Es la culminación de años de trabajo y características.
En el futuro, habrá ECMAScript 2016, que probablemente se denominará “ES7” o “ES2016”. El plan es tener lanzamientos anuales incrementales.
La mayoría de los navegadores han comenzado a implementar las funciones de ES2015, pero el soporte varía entre ellos. Puede ver la compatibilidad actual del navegador para esta implementación usando esta tabla.
Herramientas como Babel nos permiten escribir nuevo código ES2015 hoy y realizar una tarea llamada transpilación (muy parecida al preprocesamiento) para convertir el código en una versión anterior de JavaScript que tenga mayor compatibilidad con el navegador. Esto es similar a cómo funciona Sass; inicialmente escribiendo su código en sintaxis Sass, y luego un preprocesador lo compila en CSS estándar.
Descripción general
En este artículo, veremos algunas características que ahora están disponibles para usar como desarrolladores.
Examinaremos nuevas palabras clave como let
y const
, cómo crear literales de plantilla para facilitar la concatenación, la nueva sintaxis de la función de flecha, el operador de propagación y los parámetros de descanso. Aquí hay una tabla de contenido:
let
yconst
- Literales de plantilla
- Funciones de flecha
- Operadores de propagación
- Parámetros de descanso
¡Estas adiciones pueden ayudar a que escribir JavaScript sea un verdadero placer!
let
y const
let
y const
son dos nuevas palabras clave que ahora están disponibles en ES2015. Se utilizan para declarar variables, sin embargo, hay una característica clave que comparten estas variables que las distingue de var
: crean variables de ámbito de bloque.
Cuando usa el var
palabra clave para crear una variable, tiene el alcance de la función y es local solo para esa función. Esto significa que está disponible dentro de la función en la que se creó y cualquier función anidada dentro de esa. Pero NO está disponible fuera de allí. Si usaste var
para definir una variable fuera de cualquier función, estaría disponible globalmente.
Un problema común con el que nos encontraremos con las variables de ámbito de función es el for
círculo.
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // Will print out 10;
Es común declarar una variable dentro de la for
bucle con la intención de que esté vinculado a eso for
bucle sin embargo, ese no es ese caso. Si ejecuta el código anterior, verá el i
La variable está disponible fuera del bucle for.
Si quieres usar let
o const
primero tendrá que habilitar el modo estricto para su archivo JavaScript. Añadiendo 'use strict'
en la parte superior de su documento habilita una variante restringida de JavaScript.
'use strict';
El modo estricto es una forma de optar por una versión de JavaScript que corrige algunos errores en el idioma y los convierte en errores. ¡También prohíbe la sintaxis que probablemente se definirá en el futuro! Por ejemplo, en modo estricto, no puede crear una variable con el nombre de let
. Para obtener más información sobre el modo estricto, consulte la página MDN sobre el tema.
(Nota del editor: si estamos usando Babel, entonces no tenemos que preocuparnos por “usar estricto” porque lo agregará automáticamente a nuestro código, pero ciertamente vale la pena saber que sucede).
Un “bloque” en JavaScript es cualquier cosa entre { }
. Entonces, cuando hablamos de alcance de bloque, ¡eso significa que cualquier variable definida entre corchetes solo existirá en ese bloque!
var
tiene el alcance de la función, por lo que la creación de una variable dentro de un bloque con var
también lo hará disponible fuera del bloque.
{
var user = "Ryan";
}
console.log(user); // Ryan
Cuando define una variable con la let
palabra clave, creará una nueva variable solo dentro de la { }
o bloque.
{
let user = "Ryan";
}
console.log(user); // Uncaught ReferenceError: user is not defined
¡Esto define y vincula una variable solo al bloque en el que se encuentra! Si echamos un vistazo a la for
ejemplo de bucle de nuevo, y reemplace var
con let
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // Uncaught ReferenceError: i is not defined
Ahora funciona según lo previsto. El const
La palabra clave se comporta exactamente de la misma manera, con una excepción. Una vez que se define el valor base, nunca se puede redefinir. Es un valor de solo lectura.
const person = 'Ryan';
person = 'Kristen'; // Uncaught TypeError: Assignment to constant variable.
console.log(person);
El navegador arrojará un error si intenta reasignar un valor a una variable definida con const
. Dicho esto, puedes hacer algo como esto.
const person = {
name: 'Ryan'
};
person.name="Kristen";
console.log(person); // {name: 'Kristen'}
Utilizando const
no crea un valor inmutable, el valor almacenado en la variable person sigue siendo un objeto, sin embargo, acabamos de cambiar una propiedad dentro de ella. Si está buscando bloquear un objeto, mire Object.freeze()
.
Cuándo usar let
y cuando usar const
Hay un poco de debate en este momento sobre cuándo usar let
vs const
. La regla general es que si sabe que el valor no se redefinirá a lo largo de su programa, vaya con const
, si necesita un valor que pueda cambiar, vaya con let
. Hacerle saber al navegador que una variable será constante a lo largo del programa le permitirá hacer ciertos ajustes, ¡y esto podría aumentar el rendimiento!
Literales de plantilla
En ES2015 hay una nueva forma de definir una cadena y viene con algunos beneficios adicionales. Actualmente, si desea definir una cadena, puede usar ''
o ""
.
let name = "Ryan";
let job = 'Instructor';
Si desea concatenar cadenas, puede usar el +
operador.
let name = "Ryan";
let job = "Instructor";
let sentence = name + " works at HackerYou as an " + job;
console.log(sentence); // "Ryan works at HackerYou as an Instructor"
A medida que aumenta la cantidad que necesita concatenar, este patrón se vuelve bastante tedioso y rebelde. Introduzca los literales de la plantilla.
Para crear una cadena literal de plantilla, usamos la comilla invertida `
en lugar de las comillas.
let name = `Ryan`;
let job = `Instructor`;
Se comportan exactamente igual que un literal de cadena normal, pero hay una diferencia. Con un literal de plantilla, la concatenación se vuelve mucho más fácil.
let name = `Ryan`;
let job = `Instructor`;
let sentence = `${name} works at HackerYou as an ${job}`;
console.log(sentence); // "Ryan works at HackerYou as an Instructor"
Observe la ${}
sintaxis dentro de la cadena? Este es un marcador de posición de plantilla. Nos permite crear una plantilla de nuestras cadenas, y el navegador reemplazará el ${}
expresión con el valor adecuado en tiempo de ejecución. Esto hace que la concatenación de cadenas grandes sea mucho más agradable.
¡Estos nuevos marcadores de posición también te permiten realizar expresiones en el interior!
const price = 9.99;
const shipping = 3.99;
const message = `Your total with shipping will be ${price + shipping}.`;
console.log(message); // Your total with shipping will be 13.98.
Multilínea
Una última cosa a tener en cuenta con los literales de plantilla es cómo pueden manejar cadenas de varias líneas. Con una cadena normal, si quisiera que abarcara más de una línea, tendría que hacer algo como esto.
const multi = "This is a n multiline string";
console.log(multi);
Incluyendo el n
o el carácter de nueva línea obligará al texto a pasar a una nueva línea. Si intentó poner el texto en dos líneas, así:
const multi = "This is a
multiline string";
console.log(multi);
Arrojaría un error Uncaught SyntaxError: Unexpected token ILLEGAL
. Sin embargo, con los literales de plantilla PODEMOS hacer exactamente eso y agregar saltos de línea donde queramos.
const multi = `This is a
multiline string`;
console.log(multi);
¡Esto nos permite organizar nuestro marcado de una manera considerablemente más limpia!
const person = {
name: 'Ryan',
job: 'Developer/Instructor'
};
const markup = `
<div>
<h2>${person.name}</h2>
<h3>${person.job}</h3>
</div>
`;
Funciones de flecha
Las funciones de flecha son una nueva sintaxis para crear funciones en ES2015. Esto no reemplaza el function() {}
sintaxis que conocemos y amamos, pero la veremos cada vez más como la sintaxis de la función de referencia.
const add = (a, b) => {
return a + b;
};
La parte central de la sintaxis es la falta de function
palabra clave al definir una nueva función. En cambio tenemos el =>
o flecha gorda. Puede llamar a la función como lo haría con cualquier otra.
add(2, 3); // 5
En realidad, hay algunas formas de definir la función de flecha. Por ejemplo, si la función simplemente devuelve un valor y no hay nada más en el cuerpo de la función, podemos eliminar el {}
y el return
palabra clave.
const add = (a, b) => a + b;
El return
aquí está implícito, lo que significa que está implícito en lugar de que tengamos que agregar explícitamente return
a nuestro bloque. Si la función solo tiene un parámetro, puede dejar el ()
fuera de la definición de la función.
const add5 = a => a + 5;
Si no hay parámetros para usar en la función, se usan paréntesis vacíos como marcador de posición.
const eight = () => 3 + 5;
O está surgiendo un nuevo patrón en el que la gente utilizará un _
como marcador de posición en lugar del paréntesis vacío.
const eight = _ => 3 + 5;
Funciones de flecha y programación funcional
Debido a que la sintaxis de la función de flecha es muy pequeña y la mayoría de las operaciones en la programación funcional requieren muy pocas operaciones en el cuerpo de la función. ¡Esta sintaxis es una combinación perfecta para este estilo de programación!
// Without Arrow functions
const numbers = [3,4,5,6,7,8];
const doubleNumbers = numbers.map(function(n) {
return n * 2;
});
// With arrow functions
const numbers = [3,4,5,6,7,8];
const doubleNumbers = numbers.map( n => n * 2 );
¡La sintaxis le permite convertir esta agradable y sencilla operación en una sola línea!
El this
palabra clave
Un lugar con el que se debe tener cuidado al trabajar con funciones de flecha es cómo manejan las this
palabra clave. Considere un método en un objeto.
const person = {
firstName: "Ryan",
sayName: function() {
return this.firstName;
}
}
console.log(person.sayName()); // "Ryan"
Dentro de la sayName
método, el this
La palabra clave está vinculada a la person
objeto. Entonces, ejecutar el método producirá Ryan
. Con una función de flecha, el this
la palabra clave tiene un ámbito léxico. Esto significa que el alcance de la función se limitará según el lugar donde se definió. El valor de this
luego se refiere al ámbito principal.
const person = {
firstName: "Ryan",
sayName: () => {
return this.firstName;
}
}
console.log(person.sayName()); // undefined
En este ejemplo, si cambiamos el sayName
método de una función anónima a una función de flecha que devolverá undefined
! El this
estará ligado léxicamente, y en este caso será el window
objeto, en el que no hay firstName
propiedad. ¡Habrá casos en los que quizás desee que ese sea el resultado correcto! Echale un vistazo a éste ejemplo.
const person = {
firstName: 'Ryan',
hobbies: ['Robots', 'Games', 'Internet'],
showHobbies: function() {
this.hobbies.forEach(function(hobby) {
console.log(`${this.firstName} likes ${hobby}`);
});
}
};
person.showHobbies();
Ejecutar esto producirá Uncaught TypeError: Cannot read property 'firstName' of undefined
. El this
en la función de devolución de llamada para nuestro .forEach()
El método no está vinculado a nada (en modo estricto, en modo no estricto será el window
). Pero si cambiamos la devolución de llamada a una función de flecha, podemos usar la función léxica this
para obtener el valor que queremos!
const person = {
firstName: 'Ryan',
hobbies: ['Robots', 'Games', 'Internet'],
showHobbies: function() {
this.hobbies.forEach(hobby => {
console.log(`${this.firstName} likes ${hobby}`);
});
}
};
person.showHobbies();
El this
dentro de nuestro forEach
estará vinculado a la person
¡objeto!
Operadores de propagación
¡A veces queremos hacer algo con una matriz que no podemos! Por ejemplo, supongamos que tenemos una matriz de números cuyo máximo queremos encontrar. Math.max parece el método correcto para esto.
const numbers = [39, 25, 90, 123];
const max = Math.max(numbers);
console.log(max); // NaN
Math.max
es un método que toma una lista de valores separados por comas y devolverá el más alto. Lamentablemente, no podemos pasarle una matriz. Sin embargo, hay una forma de evitar esto, podemos usar un método llamado .apply
que toma una matriz y llama a una función como si la hubiéramos pasado como una lista.
const numbers = [39, 25, 90, 123];
const max = Math.max.apply(null, numbers);
console.log(max); // 123
El primer argumento en .apply
es el valor que nos gustaría establecer el this
valor para cuando llamamos Math.max
, en este ejemplo proporcionamos null
. El segundo argumento es la matriz que nos gustaría aplicar a la función. Esto podría ser un poco confuso, ¿y si hubiera una manera más fácil de hacer esto?
Ingrese el operador de propagación
En ES2015 existe el operador de propagación. La sintaxis se ve así:
...numbers
¡Lo que hace esta herramienta es extender o dispersar los elementos de la matriz! Los expandirá en su lugar. Podemos cambiar lo anterior .apply
llamada al método para que se parezca a esto ahora.
const numbers = [39, 25, 90, 123];
const max = Math.max(...numbers);
console.log(max); // 123
Spread expandirá la matriz en su lugar y pasará los elementos como si fuera una lista separada por comas.
Usando el operador de propagación para concatizar
¡También puede usar el operador de extensión para concatenar matrices juntas! Dado que spread expande matrices, ¡podemos expandir matrices en matrices!
const numbersArray1 = [3, 4, 5, 7, 8];
const numbersArray2 = [9, 6, 10, 11];
const concatArray = [...numbersArray1, ...numbersArray2];
console.log(concatArray); // [3, 4, 5, 7, 8, 9, 6, 10, 11]
Parámetros de descanso
El operador de propagación nos permite pasar una matriz de argumentos a una función. Por otro lado, los parámetros de descanso nos permiten recopilar los parámetros pasados a nuestras funciones. Al igual que el operador de propagación, la sintaxis del parámetro rest también implica la ...
al comienzo de un nombre de variable.
Veamos un ejemplo de esto. Imagina que tenemos una función que toma cualquier número de argumentos y devuelve la suma, add(2, 3, 4, 5, 6, 7)
volvería 27.
const add = function() {
const numbers = Array.prototype.slice.call(arguments);
return numbers.reduce((a,b) => a + b);
};
add(2, 3, 4, 5, 6, 7);
Sin parámetros de descanso, tendríamos que usar el arguments
palabra clave y llamar Array.prototype.slice.call(arguments)
. Que en el mundo hace Array.prototype.slice.call(arguments)
¡¿significar?! arguments
es un objeto Array-LIKE, lo que significa que no es una matriz real, sino una colección de argumentos pasados a una función. Sin embargo, si quisiéramos utilizar un método Array como .reduce()
sobre arguments
, tendríamos que tocar el violín.
JavaScript se construye a partir de un montón de objetos. Todos estos objetos tienen un objeto padre del que heredan sus métodos y propiedades. Lo hacen a través del .prototype
propiedad. Las matrices tienen el .slice
método que podemos usar para crear una matriz real a partir de nuestro arguments
valor. Utilizando .call
podemos llamar al .slice
método del prototipo con arguments
como el contexto para crear una matriz … que es mucho.
¡Ingrese los parámetros de descanso!
const add = function(...numbers) {
return numbers.reduce((a, b) => a + b);
};
add(2, 3, 4, 5, 6, 7);
¡GUAU! Eso fue mucho más fácil. Los parámetros de descanso crean una matriz real a partir de los argumentos pasados a una función, por lo que podemos usar métodos como .reduce
en eso. ¡Esto nos permite la libertad de realizar tareas similares mucho más fácilmente!
Es importante señalar que puede mezclar y combinar con los parámetros de descanso y el operador de propagación. Considere una función que toma un multiplicador como primer argumento y luego multiplica cualquier valor posterior por ese número.
const multi = (multiplier, ...numbers) => {
return numbers.map(n => n * multiplier);
}
Definimos la función con un parámetro para el multiplicador y usamos parámetros de descanso para recopilar la cantidad de argumentos que se pasen a esta función.
JavaScript avanza
Hay un montón de características en ES2015 que no revisamos aquí, pero esperamos que esto le brinde una buena base de una nueva y útil sintaxis y adiciones al lenguaje. Si desea obtener más información, consulte mi serie de videos Aprendamos ES6 en YouTube, así como letslearnes6.com, donde puede encontrar información sobre un libro que estoy escribiendo sobre ES6.