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?
