7 nuevas funciones enviadas con ES2022
7 nuevas funciones ES2022… ¡que los desarrolladores deberían estar entusiasmados!
Como sabrá, desde ES6 en 2015, TC39 de Ecma International lanza una nueva versión de ECMAScript cada año. ES2022 es la 13.ª edición de la especificación del lenguaje ECMAScript.
Esta nueva iteración viene con su propio lote de nuevas características: ¡revisémoslas!
1. Espera de nivel superior
La await
de nivel superior permite que los módulos actúen como grandes funciones asíncronas.
Con la await
de nivel superior, los módulos ECMAScript (ESM) pueden esperar
recursos, lo que hace que otros módulos que los importan
esperen antes de comenzar a evaluar su cuerpo.
// say this is my-apple.js
await Promise.resolve('🦥') // '🦥'
Casos de uso
¿Cuándo tendría sentido tener un módulo que espera a que se cargue una operación asíncrona?
Ruta de dependencia dinámica
const strings = await import(`/i18n/${navigator.language}`);
Esto permite que los módulos usen valores de tiempo de ejecución para determinar las dependencias. Esto es útil para cosas como divisiones de desarrollo/producción, internacionalización, divisiones de entorno, etc.
Inicialización de recursos
const connection = await dbConnector();
Esto permite que los Módulos representen recursos y también que produzcan errores en los casos en que el Módulo nunca se podrá utilizar.
Respaldos de dependencia
let jQuery; try { jQuery = await import('https://cdn-a.com/jQuery'); } catch { jQuery = await import('https://cdn-b.com/jQuery'); }
2. Método .at()
en todos los indexables incorporados
Actualmente, para acceder a un valor desde el final de un objeto indexable, la práctica común es escribir arr[arr.length - n]
.
Esto requiere nombrar el indexable dos veces y, además, agrega siete caracteres más para .length
y es hostil a los valores anónimos.
Además, no puede usar esta técnica para capturar el último elemento del valor de retorno de una función a menos que primero lo almacene en una variable temporal. Veamos qué podemos hacer con .at()
:
const users = ['👷♀️', '🧟♂️', '👶', '🧝', '🙋♂️'];// Until today users[users.length - 1]; // '🙋♂️' users[1]; // '🧟♂️' users[1000]; // undefined// With the .at() method; users.at(-1); // '🙋♂️' users.at(1); // '🧟♂️' users.at(1000); // undefined ["🍍", "🍏"].at(0); // "🍍"
3. Una más accesible hasOwnProperty:
Object.hasOwn
Si no posee directamente todas las propiedades definidas en un objeto, no puede estar 100 % seguro de que llamar a .hasOwnProperty()
está llamando al método integrado. Veamos este ejemplo:
let object = { hasOwnProperty() { throw new Error("gotcha!") } }object.hasOwnProperty("foo") // Uncaught Error: gotcha!
Object.hasOwn
comparte exactamente el mismo comportamiento que .hasOwnProperty()
y se implementa como tal:
let object = { foo: false } Object.hasOwn(object, "foo") // truelet object2 = Object.create({ foo: true }) Object.hasOwn(object2, "foo") // falselet object3 = Object.create(null) Object.hasOwn(object3, "foo") // false
Bueno saber
ESLint tiene una regla integrada para prohibir el uso de prototipos integrados como hasOwnProperty.
4. Índices de coincidencia RegExp
ECMAScript RegExp
Match Indices proporciona información adicional sobre los índices de inicio y finalización de las subcadenas capturadas en relación con el inicio de la cadena de entrada.
Veámoslo en acción:
const re1 = /a+(?<Z>z)?/d; // indices are relative to start of the input string: const s1 = "xaaaz"; const m1 = re1.exec(s1); m1.indices[0][0]; // 1 m1.indices[0][1]; // 5 s1.slice(...m1.indices[0]); // "aaaz" m1.indices[1][0]; // 4 m1.indices[1][1]; // 5 s1.slice(...m1.indices[1]); // "z" m1.indices.groups["Z"][0]; // 4 m1.indices.groups["Z"][1]; // 5 s1.slice(...m1.indices.groups["Z"]); // "z" // capture groups that are not matched return `undefined`: const m2 = re1.exec("xaaay"); m2.indices[1]; // undefined m2.indices.groups["Z"]; // undefined
Bueno saber
Por razones de rendimiento, los indices
solo se agregarán al resultado si se especifica el indicador d.
5. Causa del error
Para ayudar a diagnosticar comportamientos inesperados, los errores deben complementarse con información contextual, como mensajes de error y propiedades de instancias de errores, para explicar lo que sucedió en ese momento.
Si el error se generó a partir de métodos internos profundos, es posible que el error generado no se realice de manera directa y eficiente sin un patrón de diseño de excepción adecuado.
Ahora, Error
()
acepta un parámetro de opciones adicional: la propiedad cause
. La cause
se asignará a las instancias de error como una propiedad. Esto significa que los errores se pueden encadenar sin trámites innecesarios y demasiado elaborados para envolver los errores en condiciones:
async function doJob() { const rawResource = await fetch('//domain/resource-a') .catch(err => { throw new Error( 'Download raw resource failed', { cause: err } ); }); const jobResult = doComputationalHeavyJob(rawResource); await fetch( '//domain/upload', { method: 'POST', body: jobResult } ).catch(err => { throw new Error('Upload job result failed', { cause: err }); }); } try { await doJob(); } catch (e) { console.log(e); console.log('Caused by', e.cause); } // Error: Upload job result failed // Caused by TypeError: Failed to fetch
6. Comprobaciones de marca ergonómicas para campos privados
Esta nueva característica propone una forma compacta de verificar si un objeto tiene un campo privado dado.
class ClassA { #name; static hasName(obj) { return #name in obj; // } } class ClassB { hello () { return 'Hello'; } } const myClassA = new ClassA(); const myClassB = new ClassB(); ClassA.hasName(myClassA); // true; ClassA.hasName(myClassB); // false;
Conclusión
¡Eso es todo para este ES2022! ¡Buen trabajo por llegar al final del artículo!
Como desarrollador, mantenerse al día con la evolución del lenguaje es clave para su crecimiento.
¿Cuál de esas características es la más emocionante para ti?
¡Gracias por leer!
Si le interesa, puede echar un vistazo a algunos de los otros artículos que he escrito recientemente sobre Laravel: