Hoy publicamos la segunda parte de la traducción de las innovaciones de JavaScript. Aquí hablamos sobre separadores de dígitos de números, sobre números BigInt, sobre trabajar con matrices y objetos, sobre 
globalThis , sobre clasificación, sobre la API de internacionalización y sobre promesas.

→ 
La primera parteSeparadores de números
Los números largos que se encuentran en los programas son difíciles de leer. Por ejemplo, 
1000000000 es mil millones en decimal. Pero de un vistazo es difícil de entender. Por lo tanto, si el lector del programa encuentra algo similar, él, para percibirlo correctamente, tendrá que considerar cuidadosamente los ceros.
En JavaScript moderno, puede usar el separador de dígitos de números, un guión bajo ( 
_ ), cuyo uso mejora la legibilidad de los números largos. Así es como se ven los números escritos usando un delimitador en el código:
 var billion = 1_000_000_000; console.log( billion );  
Los separadores se pueden usar para dividir arbitrariamente los números en fragmentos. JavaScript, cuando se trata de números, simplemente ignora los separadores. Se pueden usar al escribir cualquier número: enteros, coma flotante, binario, hexadecimal, octal.
 console.log( 1_000_000_000.11 );  
→ Soporte
- TC39: Etapa 3
- Chrome: más de 75
- Nodo: 12.5+
Tipo de datos Bigint
Los números en JavaScript se crean utilizando la función de constructor de 
Number .
El valor máximo que se puede representar de forma segura usando el tipo de datos 
Number es (2⁵³ - 1), es decir, 9007199254740991. Puede ver este número usando la construcción 
Number.MAX_SAFE_INTEGER .
Tenga en cuenta que cuando se usa un literal numérico en el código JS, JavaScript lo procesa, creando un objeto basado en él usando el constructor de 
Number . El prototipo de este objeto contiene métodos para trabajar con números. Esto sucede con todos 
los tipos de datos primitivos .
¿Qué sucederá si intentamos agregar algo al número 9007199254740991?
 console.log( Number.MAX_SAFE_INTEGER );  
El resultado de agregar 
Number.MAX_SAFE_INTEGER y 10, la segunda salida de 
console.log() , es incorrecto. Esto se debe al hecho de que JS no puede realizar correctamente los cálculos con números mayores que el valor de 
Number.MAX_SAFE_INTEGER . Puede resolver este problema utilizando el 
bigint datos 
bigint .
El tipo 
bigint permite representar enteros mayores que 
Number.MAX_SAFE_INTEGER . Trabajar con valores BigInt es similar a trabajar con valores de tipo 
Number . En particular, el lenguaje tiene la función 
BigInt() , con la que puede crear los valores correspondientes, y el 
bigint datos primitivo 
bigint incorporado utilizado para representar enteros grandes.
 var large = BigInt( 9007199254740991 ); console.log( large );  
JavaScript agrega 
n al final de los literales BigInt. Para nosotros, esto significa que tales literales se pueden escribir agregando 
n al final de los enteros.
Ahora que tenemos números BigInt a nuestra disposición, podemos realizar operaciones matemáticas con seguridad en grandes números de tipo 
bigint .
 var large = 9007199254740991n; console.log( large + 10n );  
Un número de número de tipo no es lo mismo que un número de tipo 
bigint . En particular, estamos hablando del hecho de que los números BigInt solo pueden ser enteros. Como resultado, resulta que no puede realizar operaciones aritméticas que usen los tipos 
bigint y 
number .
Cabe señalar que la función 
BigInt() puede tomar varios números: decimal, binario, hexadecimal, octal. Dentro de esta función, se convertirán en números, para cuya representación se utiliza el sistema de números decimales.
El tipo 
bigint también admite separadores de bits:
 var large = 9_007_199_254_741_001n; console.log( large );  
→ Soporte
Nuevos métodos de matriz: .flat () y .flatMap ()
Aquí hablaremos sobre los nuevos métodos prototipo para el objeto 
Array : los 
.flat() y 
.flatMap() .
Método fla .flat ()
Ahora los objetos de tipo 
Array tienen un nuevo método: 
.flat(n) . Devuelve una nueva matriz, lo que permite elevar recursivamente los elementos de las matrices al nivel especificado 
n . Por defecto, 
n es 1. Este método puede pasar 
n igual a 
Infinity , lo que le permite convertir una matriz con matrices anidadas en una matriz unidimensional.
 var nums = [1, [2, [3, [4, 5]]]]; console.log( nums.flat() );  
→ Soporte
Método method .flatMap ()
Al resolver tareas cotidianas, el programador a veces puede necesitar procesar la matriz usando el método 
.map() con su posterior transformación en una estructura plana. Por ejemplo, cree una matriz que contenga los números y cuadrados de estos números:
 var nums = [1, 2, 3]; var squares = nums.map( n => [ n, n*n ] ) console.log( squares );  
La solución a este problema se puede simplificar usando el método 
.flatMap() . Convierte las matrices devueltas por la función de devolución de llamada que se le pasó, tal como convertirían su método 
.flat() con el parámetro 
n igual a 1.
 var nums = [1, 2, 3]; var makeSquare = n => [ n, n*n ]; console.log( nums.flatMap( makeSquare ) );  
→ Soporte
▍ Método Object.fromEntries ()
Es posible extraer pares de 
: tipo de un objeto 
: se puede usar usando el 
Object método estático, que devuelve una matriz, cada elemento de la cual es una matriz que contiene, como primer elemento, una clave, y como segundo, un valor.
 var obj = { x: 1, y: 2, z: 3 }; var objEntries = Object.entries( obj ); console.log( objEntries );  
Ahora tenemos a nuestra disposición un método estático 
Object.fromEntries() , que nos permite convertir una estructura similar en un objeto.
 var entries = [["x", 1],["y", 2],["z", 3]]; var obj = Object.fromEntries( entries ); console.log( obj );  
El método de 
entries() se utilizó para facilitar el filtrado y el mapeo de datos almacenados en objetos. El resultado es una matriz. Pero hasta ahora, la tarea de convertir dicha matriz en un objeto no ha tenido una solución hermosa. Es para resolver este problema que puede usar el método 
Object.fromEntries() .
 var obj = { x: 1, y: 2, z: 3 };  
Si la estructura 
Map : datos se usa para almacenar los pares 
: , entonces los datos se almacenan en el orden en que se agregaron. Al mismo tiempo, la forma en que se almacenan los datos se asemeja a la matriz devuelta por el método 
Object.entries() . El método 
Object.fromEntries() es fácil de usar para transformar estructuras de datos de 
Map en objetos.
 var m = new Map([["x", 1],["y", 2],["z", 3]]); console.log( m );  
→ Soporte
▍ Propiedad global globalThis
Estamos familiarizados con 
this utilizada en JavaScript. No tiene un valor fijo. En cambio, el significado de 
this depende del contexto en el que se accede. En cualquier entorno, la 
this apunta a un objeto global cuando se accede desde el contexto del nivel más alto. Este es el significado global de 
this .
En JavaScript basado en navegador, por ejemplo, el valor global para 
this es el objeto de 
window . Puede verificar esto utilizando la construcción 
console.log(this) en el nivel superior del archivo JavaScript (en el contexto más externo) o en la consola JS del navegador.
Accediendo a esto en la consola del navegadorEl valor global de 
this en Node.js apunta a un objeto 
global . Dentro de un trabajador web, apunta al trabajador mismo. Sin embargo, obtener el valor global de 
this no es una tarea fácil. El hecho es que no puedes referirte a 
this ningún lado. Por ejemplo, si intenta hacer esto en el constructor de la clase, resulta que 
this apunta a una instancia de la clase correspondiente.
En algunos entornos, la 
this self se puede utilizar para acceder al valor global de 
this . Esta palabra clave juega el mismo papel que los mecanismos para acceder a este valor en los navegadores, en Node.js y en los trabajadores web. Usando el conocimiento de cómo se llama el valor global de 
this en diferentes entornos, puede crear una función que devuelva este valor:
 const getGlobalThis = () => { if (typeof self !== 'undefined') return self; if (typeof window !== 'undefined') return window; if (typeof global !== 'undefined') return global; if (typeof this !== 'undefined') return this; throw new Error('Unable to locate global `this`'); }; var globalThis = getGlobalThis(); 
Ante nosotros hay un polyfill primitivo para obtener el objeto global. Lea más sobre esto 
aquí . JavaScript ahora tiene la palabra clave 
globalThis . Proporciona una forma universal de acceder al valor global de 
this para diferentes entornos y no depende de la ubicación del programa desde el que se accede.
 var obj = { fn: function() {  console.log( 'this', this === obj );  
→ Soporte
Clasificación estable
El estándar ECMAScript no ofrece un algoritmo de ordenación de matriz específico que los motores JavaScript deberían implementar. Solo describe la API utilizada para ordenar. Como resultado, al usar diferentes motores JS, uno puede encontrar diferencias en el rendimiento de las operaciones de clasificación y en la estabilidad (estabilidad) de los algoritmos de clasificación.
Ahora el estándar 
requiere que los arreglos de clasificación sean estables. Los detalles sobre la estabilidad de la clasificación se pueden encontrar 
aquí . La esencia de esta característica de los algoritmos de clasificación es la siguiente. El algoritmo es estable si el resultado de la clasificación, que es una matriz modificada, contiene elementos con los mismos valores que no se vieron afectados por la clasificación en el mismo orden en que se colocaron en la matriz original. Considere un ejemplo:
 var list = [  { name: 'Anna', age: 21 },  { name: 'Barbra', age: 25 },  { name: 'Zoe', age: 18 },  { name: 'Natasha', age: 25 } ];  
Aquí, la matriz de 
list contiene los objetos se ordena por el campo de 
age de estos objetos. En la matriz de 
list , un objeto con la propiedad de 
name igual a 
Barbra se encuentra antes del objeto con la propiedad de 
name igual a 
Natasha . Dado que 
age valores de 
age de estos objetos son iguales, podríamos esperar que en la matriz ordenada estos elementos retengan el orden de disposición anterior entre sí. Sin embargo, en la práctica esto no puede esperarse. La forma exacta en que se formará la matriz ordenada dependía completamente del motor JS utilizado.
Ahora todos los navegadores modernos y Node.js usan un algoritmo de ordenación estable, llamado al acceder al método de matriz 
.sort() . Esto le permite siempre, para los mismos datos, obtener el mismo resultado:
 
En el pasado, algunos motores JS admitían una clasificación estable, pero solo para arreglos pequeños. Para mejorar el rendimiento al procesar matrices grandes, podrían usar algoritmos más rápidos y sacrificar la estabilidad de clasificación.
→ Soporte
- Chrome: 70+
- Nodo: 12+
- Firefox: 62+
API de internacionalización
La API de internacionalización está diseñada para organizar comparaciones de cadenas, para formatear números, fechas y horas, como es habitual en varios estándares regionales (locales). El acceso a esta API se organiza a través 
del objeto Intl . Este objeto proporciona constructores para crear objetos de clasificación y objetos que formatean datos. La lista de configuraciones regionales admitidas por el objeto 
Intl se puede encontrar 
aquí .
▍Intl.RelativeTimeFormat ()
En muchas aplicaciones, a menudo es necesario mostrar el tiempo en un formato relativo. Puede parecer "hace 5 minutos", "ayer", "hace 1 minuto", y así sucesivamente. Si los materiales del sitio web se traducen a diferentes idiomas, debe incluir todas las combinaciones posibles de construcciones relativas que describan el tiempo en el ensamblaje del sitio.
JS ahora tiene 
el Intl.RelativeTimeFormat(locale, config) , que le permite crear sistemas de formato de fecha y hora para diferentes configuraciones regionales. En particular, estamos hablando de objetos que tienen un 
método .format(value, unit) , que le permite generar varias marcas de tiempo relativas. Se ve así:
 
→ Soporte
▍Intl.ListFormat ()
El constructor 
Intl.ListFormat permite combinar elementos de la lista usando las palabras 
and ( 
) y 
or ( 
). Al crear el objeto correspondiente, al constructor se le pasa la configuración regional y el objeto con los parámetros. Su parámetro de 
type puede ser 
conjunction , 
disjunction y 
unit . Por ejemplo, si queremos combinar los elementos de 
[apples, mangoes, bananas] usando un objeto de conjunción, obtenemos una cadena de la forma 
apples, mangoes and bananas . Si usamos un objeto de disyunción, obtenemos una cadena de 
apples, mangoes or bananas .
El objeto creado por 
el constructor Intl.ListFormat tiene 
un .format(list) que combina listas. Considere un ejemplo:
 
→ Soporte
▍Intl.Locale ()
El concepto de "estándar regional" suele ser mucho más que el simple nombre de un idioma. Esto puede incluir el tipo de calendario, información sobre los ciclos de tiempo utilizados y los nombres de los idiomas. 
El constructor Intl.Locale(localeId, config) usa para crear cadenas de 
Intl.Locale(localeId, config) formateadas basadas en el objeto de 
config que se le pasa.
Intl.Locale objeto creado con 
Intl.Locale contiene todas las configuraciones regionales especificadas. Su método 
.toString() produce una cadena estándar regional formateada.
 const krLocale = new Intl.Locale( 'ko', {  script: 'Kore', region: 'KR',  hourCycle: 'h12', calendar: 'gregory' } ); console.log( krLocale.baseName );  
Aquí puede leer sobre identificadores y etiquetas locales en Unicode.
→ Soporte
Promesas
A partir de ahora, JS tiene los métodos estáticos 
Promise.all() y 
Promise.race() . El 
Promise.all([...promises]) devuelve una promesa que se resuelve con éxito después de que se resuelven todas las promesas pasadas al método como argumento. Esta promesa es rechazada en el caso de que al menos una de las promesas transferidas a ella sea rechazada. El 
Promise.race([...promises]) devuelve una promesa, que se resuelve después de que se resuelve cualquiera de las promesas transferidas y se rechaza si se rechaza al menos una de esas promesas.
La comunidad de desarrolladores de JS estaba desesperada por un método estático, la promesa devuelta que se resolvería después de que todas las promesas que se le pasaran se completaran (permitidas o rechazadas). Además, necesitábamos un método similar a 
race() , que devolvería una promesa a la espera de la resolución de cualquiera de las promesas que se le pasaran.
Method Método Promise.allSettled ()
El método 
Promise.allSettled() acepta una serie de promesas. La promesa devuelta por él está permitida después de que todas las promesas sean rechazadas o permitidas. El resultado es que la promesa devuelta por este método no necesita un 
catch .
El hecho es que esta promesa siempre se resuelve con éxito. El bloque 
then recibe el 
status y el 
value de cada promesa en el orden en que aparecen.
 var p1 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val1' ), 2000 ) ); var p2 = () => new Promise(  (resolve, reject) => setTimeout( () => resolve( 'val2' ), 2000 ) ); var p3 = () => new Promise(  (resolve, reject) => setTimeout( () => reject( 'err3' ), 2000 ) ); var p = Promise.allSettled( [p1(), p2(), p3()] ).then(  ( values ) => console.log( values ) );  
→ Soporte
▍ Método Promise.any ()
El método 
Promise.any() es similar a 
Promise.race() , pero la promesa que devuelve no ejecuta el 
catch cuando se rechaza una de las promesas pasadas a este método.
En cambio, espera la resolución de todas las promesas. Si no se permitieron promesas, se ejecutará el bloque 
catch . Si alguna de las promesas se resuelve con éxito, se ejecutará.
Resumen
En este artículo, analizamos algunas de las innovaciones de JavaScript discutidas en la conferencia 
Google I / O 2019 . Esperamos que encuentre algo entre ellos que le sea útil.
Estimados lectores! ¿Qué extrañas especialmente en JavaScript?
