Hoy, en la novena parte de la traducción del manual de JavaScript, se ofrecerá una descripción general de las características que han aparecido en el idioma gracias a los estándares ES7, ES8 y ES9.
→ 
Parte 1: primer programa, características del lenguaje, estándares→ 
Parte 2: estilo de código y estructura del programa→ 
Parte 3: variables, tipos de datos, expresiones, objetos.→ 
Parte 4: características→ 
Parte 5: matrices y bucles→ 
Parte 6: excepciones, punto y coma, literales comodín→ 
Parte 7: modo estricto, esta palabra clave, eventos, módulos, cálculos matemáticos→ 
Parte 8: Descripción general de las características de ES6→ 
Parte 9: Descripción general de los estándares ES7, ES8 y ES9
Estándar ES7
El estándar ES7, que, de acuerdo con la terminología oficial, se llama ES2016, se lanzó en el verano de 2016. Él, en comparación con ES6, traído al lenguaje no es mucho nuevo. En particular, estamos hablando de lo siguiente:
- Array.prototype.includes()método.
- Operador de exponenciación.
▍ Método Array.prototype.includes ()
El método 
Array.prototype.includes() está diseñado para verificar la presencia de un elemento en la matriz. Al encontrar lo deseado en la matriz, devuelve 
true , no encontrar, 
false . Antes de ES7, el método 
indexOf() se usaba para realizar la misma operación, que devuelve, si se encuentra un elemento, el primer índice por el cual se puede encontrar en la matriz. Si 
indexOf() no encuentra el elemento, devuelve el número 
-1 .
De acuerdo con las reglas de conversión de tipo JavaScript, el número 
-1 convierte en 
true . Como resultado, para verificar los resultados de la operación de 
indexOf() se debe usar una construcción no particularmente conveniente del siguiente formulario.
 if ([1,2].indexOf(3) === -1) { console.log('Not found') } 
Si en una situación similar, suponiendo que 
indexOf() , sin encontrar un elemento, devuelve 
false , use algo como el que se muestra a continuación, el código no funcionará correctamente.
 if (![1,2].indexOf(3)) {  
En este caso, resulta que la construcción 
![1,2].indexOf(3) da 
false .
Usando el método 
includes() , tales comparaciones parecen mucho más lógicas.
 if (![1,2].includes(3)) { console.log('Not found') } 
En este caso, la construcción 
[1,2].includes(3) devuelve 
false , ¡este valor es un operador 
! se convierte en 
true y la consola recibe un mensaje que indica que no se encontró el elemento en la matriz.
▍ operador de exponenciación
El operador de exponenciación realiza la misma función que el método 
Math.pow() , pero es más conveniente usarlo que una función de biblioteca, ya que es parte del lenguaje.
 Math.pow(4, 2) == 4 ** 2  
Este operador puede considerarse una adición agradable a JS, que es útil en aplicaciones que realizan ciertos cálculos. Existe un operador similar en otros lenguajes de programación.
Estándar ES8
El estándar ES8 (ES2017) se lanzó en 2017. Él, como ES7, no aportó mucho al idioma. A saber, estamos hablando de las siguientes características:
- Agregar cadenas a una longitud determinada.
- Método Object.values().
- Método Object.entries().
- Método Object.getOwnPropertyDescriptors().
- Comas finales en los parámetros de la función.
- Funciones asincrónicas.
- Trabajar con memoria compartida y operaciones atómicas.
▍ Agregar líneas a una longitud dada
ES8 introdujo dos nuevos métodos de objeto 
String : 
padStart() y 
padEnd() .
El método 
padStart() llena la línea actual con otra línea hasta que la línea final alcanza la longitud deseada. El llenado ocurre al comienzo de la línea (izquierda). Aquí se explica cómo usar este método.
 str.padStart(targetLength [, padString]) 
Aquí 
str es la línea actual, 
targetLength es la longitud de la línea final (si es menor que la longitud de la línea actual, esta línea se devolverá sin cambios), 
padString es un parámetro opcional: la línea utilizada para llenar la línea actual. Si no se especifica 
padString , se utiliza un carácter de espacio para 
padString línea actual a la longitud especificada.
El método 
padEnd() es similar a 
padStart() , pero la línea se rellena a la derecha.
Considere ejemplos de uso de estos métodos.
 const str = 'test'.padStart(10) const str1 = 'test'.padEnd(10,'*') console.log(`'${str}'`)  
Aquí, cuando se usa 
padStart() con solo la longitud deseada de la cadena resultante, se agregaron espacios al comienzo de la cadena original. Al usar 
padEnd() con la longitud de la línea final y la línea para llenarla, los caracteres 
* se agregaron al final de la línea original.
▍ Método Object.values ()
Este método devuelve una matriz que contiene los valores de las propiedades propias del objeto, es decir, las propiedades que contiene el objeto en sí y no las que son accesibles a través de la cadena de prototipos.
Aquí se explica cómo usarlo.
 const person = { name: 'Fred', age: 87 } const personValues = Object.values(person) console.log(personValues)  
Este método también se aplica a las matrices.
▍ Método Object.entries ()
Este método devuelve una matriz, cada elemento del cual también es una matriz que contiene, en el formato 
[key, value] , claves y valores de las propiedades del objeto.
 const person = { name: 'Fred', age: 87 } const personValues = Object.entries(person) console.log(personValues)  
Al aplicar este método a las matrices, los índices de los elementos se muestran como claves, y lo que se almacena en la matriz en los índices correspondientes se muestra como valores.
▍ método getOwnPropertyDescriptors ()
Este método devuelve información sobre todas las propiedades del objeto. Los conjuntos de atributos (descriptores) están asociados con las propiedades del objeto. En particular, estamos hablando de los siguientes atributos:
- value: el valor de la propiedad del objeto.
- writable: contiene- truesi la propiedad se puede cambiar.
- get: contiene una función getter asociada con la propiedad o, si no existe,- undefined.
- set: contiene la función setter de la propiedad o- undefined.
- configurable, si es- false, la propiedad no se puede eliminar, sus atributos no se pueden cambiar, excepto el valor.
- enumerable: si verdadero está contenido en esta propiedad, la
Aquí se explica cómo usar este método.
 Object.getOwnPropertyDescriptors(obj) 
Toma un objeto cuya información de propiedad necesita averiguar y devuelve un objeto que contiene esta información.
 const person = { name: 'Fred', age: 87 } const propDescr = Object.getOwnPropertyDescriptors(person) console.log(propDescr)  
¿Por qué se necesita este método? El hecho es que le permite crear pequeñas copias de objetos, copiando, además de otras propiedades, captadores y establecedores. Esto no se pudo hacer usando el método 
Object.assign() , que apareció en el estándar ES6, para copiar objetos.
El siguiente ejemplo tiene un objeto con un setter que muestra, usando 
console.log() , lo que están tratando de escribir en su propiedad correspondiente.
 const person1 = { set name(newName) {     console.log(newName) } } person1.name = 'x'  
Intentemos copiar este objeto usando el método 
assign() .
 const person2 = {} Object.assign(person2, person1) person2.name = 'x'  
Como puede ver, este enfoque no funciona. La propiedad de 
name , que fue la que establece el objeto original, ahora se representa como una propiedad normal.
Ahora 
Object.defineProperties() el objeto utilizando los métodos 
Object.defineProperties() (apareció en ES5.1) y 
Object.getOwnPropertyDescriptors() .
 const person3 = {} Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1)) person3.name = 'x'  
Aquí, el colocador permanece en la copia del objeto.
Cabe señalar que las restricciones específicas de 
Object.assign() también son características del método 
Object.create() cuando se utiliza para clonar objetos.
▍Comas de terminación en parámetros de función
Esta característica le permite dejar una coma al final de la lista de parámetros o argumentos, respectivamente, al declarar y al llamar a funciones.
 const doSomething = ( var1, var2, ) => {  
Esto mejora la usabilidad de los sistemas de control de versiones. Es decir, estamos hablando del hecho de que al agregar nuevos parámetros a una función, no tiene que cambiar el código existente solo por insertar una coma.
▍Funciones asincrónicas
La construcción 
async/await ha aparecido en el estándar ES2017, que puede considerarse la innovación más importante de esta versión del lenguaje.
Las funciones asincrónicas son una combinación de promesas y generadores; simplifican las construcciones que anteriormente requerían una gran cantidad de código de plantilla y cadenas de promesas inconvenientes para describir. De hecho, estamos hablando de una abstracción de alto nivel sobre las promesas.
Cuando aparecieron las promesas en el estándar ES2015, fueron diseñadas para resolver problemas existentes con código asincrónico, lo que hicieron. Pero durante los dos años que compartieron los estándares ES2015 y ES2017, quedó claro que las promesas no pueden considerarse la solución final a estos problemas.
En particular, las promesas estaban destinadas a resolver el problema del "infierno de devolución de llamada", pero, al resolver este problema, ellos mismos no mostraron su mejor lado debido a la complejidad del código en el que se utilizan. De hecho, la construcción 
async/await resuelve el problema de las promesas y mejora la usabilidad del código asíncrono.
Considera un ejemplo.
 function doSomethingAsync() { return new Promise((resolve) => {     setTimeout(() => resolve('I did something'), 3000) }) } async function doSomething() { console.log(await doSomethingAsync()) } console.log('Before') doSomething() console.log('After') 
Este código enviará lo siguiente a la consola.
 Before After I did something 
Como puede ver, después de llamar a 
doSomething() programa continúa ejecutándose, después de que se muestre 
Before , 
After en la consola, y después de que hayan pasado tres segundos, 
I did something .
Llamada de función asíncrona en serie
Si es necesario, las funciones asincrónicas pueden formar algo así como cadenas de llamadas. Dichos diseños se distinguen por una mejor legibilidad que algo similar, basado únicamente en promesas. Esto se puede ver en el siguiente ejemplo.
 function promiseToDoSomething() { return new Promise((resolve)=>{     setTimeout(() => resolve('I did something'), 10000) }) } async function watchOverSomeoneDoingSomething() { const something = await promiseToDoSomething() return something + ' and I watched' } async function watchOverSomeoneWatchingSomeoneDoingSomething() { const something = await watchOverSomeoneDoingSomething() return something + ' and I watched as well' } watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => { console.log(res)  
▍ Memoria compartida y operaciones atómicas
Aquí estamos hablando del objeto 
SharedArrayBuffer , que le permite describir áreas de memoria compartida, y el objeto 
Atomics , que contiene un conjunto de operaciones atómicas en forma de métodos estáticos. Los detalles sobre las posibilidades que estos objetos le dan al programador se pueden encontrar 
aquí .
Estándar ES9
ES9 (ES2018) es la última versión del estándar en el momento de la publicación de este material. Estas son sus principales características:
- Aplicar declaraciones de propagación y descanso a los objetos.
- Iteradores asincrónicos.
- Método Promise.prototype.finally().
- Mejoras en la expresión regular.
▍ Aplicación de operadores de dispersión y descanso a objetos
Ya hemos hablado sobre el resto y los operadores de propagación que aparecieron en ES6 y se pueden usar para trabajar con matrices. Ambos parecen tres puntos. El operador rest, en el siguiente ejemplo de desestructuración de una matriz, le permite poner sus elementos primero y segundo en las constantes 
first y 
second , y todo el resto en los 
others constantes.
 const numbers = [1, 2, 3, 4, 5] const [first, second, ...others] = numbers console.log(first)  
El operador de 
spread permite pasar matrices a funciones que esperan listas de parámetros regulares.
 const numbers = [1, 2, 3, 4, 5] const sum = (a, b, c, d, e) => a + b + c + d + e const res = sum(...numbers) console.log(res)  
Ahora, utilizando el mismo enfoque, puede trabajar con objetos. Aquí hay un ejemplo del uso de la declaración rest en una operación de asignación destructiva.
 const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } console.log(first)  
Aquí está la declaración de propagación utilizada al crear un nuevo objeto basado en uno existente. Este ejemplo continúa el anterior.
 const items = { first, second, ...others } console.log(items)  
▍ iteradores asincrónicos
La nueva construcción 
for-await-of permite llamar a funciones asincrónicas que devuelven promesas en bucles. Tales bucles esperan la resolución de la promesa antes de pasar al siguiente paso. Así es como se ve.
 for await (const line of readLines(filePath)) { console.log(line) } 
Al mismo tiempo, debe tenerse en cuenta que tales bucles deben usarse en funciones asincrónicas, de la misma manera que cuando se trabaja con la construcción 
async/await .
Method Método Promise.prototype.finally ()
Si la promesa se resuelve con éxito, se llama al siguiente método 
then() . Si algo sale mal, se llama al método 
catch() . El método 
finally() permite ejecutar algo de código independientemente de lo que sucedió antes.
 fetch('file.json') .then(data => data.json()) .catch(error => console.error(error)) .finally(() => console.log('finished')) 
▍ Mejoras de expresión regular
Las expresiones regulares tienen la capacidad de verificar retrospectivamente las cadenas ( 
?<= ). Esto le permite buscar ciertas construcciones en las líneas antes de las cuales hay otras construcciones.
La capacidad de preceder las comprobaciones utilizando el constructo 
?= Estaba presente en expresiones regulares implementadas en JavaScript antes del estándar ES2018. Dichas verificaciones le permiten saber si otro fragmento sigue a cierto fragmento de una línea.
 const r = /Roger(?= Waters)/ const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1)  
Construcción 
?! realiza la operación opuesta: se encontrará una coincidencia solo si otra línea no sigue la línea dada.
 const r = /Roger(?! Waters)/g const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1)  
En la verificación retrospectiva, como ya se mencionó, 
?<= utiliza la construcción 
?<= .
 const r = /(?<=Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1)  
La operación opuesta a la descrita se puede realizar utilizando la construcción 
?<! .
 const r = /(?<!Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1)  
Secuencias de escape de expresiones regulares Unicode
En las expresiones regulares, puede usar la clase 
\d que coincide con cualquier dígito, la clase 
\s que coincide con cualquier carácter de espacio en blanco, la clase 
\w que coincide con cualquier carácter alfanumérico, etc. La función en cuestión amplía el conjunto de clases que se pueden usar en expresiones regulares, lo que le permite trabajar con secuencias Unicode. Estamos hablando de la clase 
\p{} y la inversa de la clase 
\P{} .
En Unicode, cada personaje tiene un conjunto de propiedades. Estas propiedades se indican entre llaves del grupo 
\p{} . Entonces, por ejemplo, la propiedad 
Script determina la familia de idiomas a la que pertenece un carácter, la propiedad 
ASCII , lógica, toma 
true para los caracteres ASCII, y así sucesivamente. Por ejemplo, descubriremos si algunas líneas contienen solo caracteres ASCII.
 console.log(r.test('abc'))  
La propiedad 
ASCII_Hex_Digit es 
true solo para los caracteres que se pueden usar para escribir números hexadecimales.
 const r = /^\p{ASCII_Hex_Digit}+$/u console.log(r.test('0123456789ABCDEF'))  
Hay muchas otras propiedades similares que se utilizan de la misma manera que se describe anteriormente. Entre ellos se encuentran 
Uppercase , 
Lowercase , 
White_Space , 
Alphabetic , 
Emoji .
Por ejemplo, a continuación se explica cómo usar la propiedad 
Script para determinar qué alfabeto se usa en una cadena. Aquí verificamos la cadena para el uso del alfabeto griego.
 const r = /^\p{Script=Greek}+$/u console.log(r.test('ελληνικά'))  
Los detalles sobre estas propiedades se pueden encontrar 
aquí .
Grupos nombrados
Los grupos de caracteres capturados en ES2018 pueden recibir nombres. Así es como se ve.
 const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ const result = re.exec('2015-01-02') console.log(result)  
Sin el uso de grupos con nombre, los mismos datos solo estarían disponibles como elementos de matriz.
 const re = /(\d{4})-(\d{2})-(\d{2})/ const result = re.exec('2015-01-02') console.log(result)  
Bandera de Regex
Usar la bandera 
s da como resultado un personaje 
. (dot) coincidirá, entre otros, con el carácter de nueva línea. Sin esta bandera, un punto coincide con cualquier carácter, excepto una nueva línea.
 console.log(/hi.welcome/.test('hi\nwelcome'))  
Resumen
Con este material, estamos completando la publicación de las traducciones de 
este manual de JavaScript. Esperamos que estas publicaciones hayan ayudado a aquellos que no habían trabajado con JavaScript antes a dar sus primeros pasos en la programación en este lenguaje.
Estimados lectores! Si no ha escrito en JS antes y ha dominado este idioma en esta guía, comparta sus impresiones.
