Post Top Ad

Your Ad Spot

domingo, 28 de junio de 2020

Característica ECMAScript: encadenamiento opcional



Esta publicación de blog describe la propuesta de ECMAScript "Encadenamiento opcional" de Gabriel Isenberg, Claude Pache y Dustin Savery.

Resumen   

Existen los siguientes tipos de operaciones opcionales.
obj?.prop     // optional static property access
obj?.[«expr»] // optional dynamic property access
func?.(«arg0», «arg1») // optional function or method call
La idea aproximada es:
  • Si el valor antes del signo de interrogación no es ni undefinedtampoco null, realice la operación después del signo de interrogación.
  • De lo contrario, regrese undefined.

Ejemplo: acceso a propiedad estática opcional   

Considere los siguientes datos:
const persons = [
  {
    surname: 'Zoe',
    address: {
      street: {
        name: 'Sesame Street',
        number: '123',
      },
    },
  },
  {
    surname: 'Mariner',
  },
  {
    surname: 'Carmen',
    address: {
    },
  },
];
Podemos usar el encadenamiento opcional para extraer de forma segura los nombres de las calles:
const streetNames = persons.map(
  p => p.address?.street?.name);
assert.deepEqual(
  streetNames, ['Sesame Street', undefined, undefined]
);

Manejo de valores predeterminados a través de fusión nula   

El operador de fusión nulo propuesto nos permite usar el valor predeterminado en '(no street)'lugar de undefined:
const streetNames = persons.map(
  p => p.address?.street?.name ?? '(no name)');
assert.deepEqual(
  streetNames, ['Sesame Street', '(no name)', '(no name)']
);

(Avanzado)   

Las secciones restantes cubren aspectos avanzados de encadenamiento opcional.

Los operadores con más detalle   

Acceso a propiedad estática opcional   

Las siguientes dos expresiones son equivalentes:
o?.prop
(o !== undefined && o !== null) ? o.prop : undefined
Ejemplos:
assert.equal(undefined?.prop, undefined);
assert.equal(null?.prop,      undefined);
assert.equal({prop:1}?.prop,  1);

Acceso a la propiedad dinámica opcional   

Las siguientes dos expresiones son equivalentes:
o?.[«expr»]
(o !== undefined && o !== null) ? o[«expr»] : undefined
Ejemplos:
const key = 'prop';
assert.equal(undefined?.[key], undefined);
assert.equal(null?.[key], undefined);
assert.equal({prop:1}?.[key], 1);

Función opcional o llamada al método   

Las siguientes dos expresiones son equivalentes:
f?.(arg0, arg1)
(f !== undefined && f !== null) ? f(arg0, arg1) : undefined
Ejemplos:
assert.equal(undefined?.(123), undefined);
assert.equal(null?.(123), undefined);
assert.equal(String?.(123), '123');
Tenga en cuenta que este operador produce un error si su lado izquierdo no es invocable:
assert.throws(
  () => true?.(123),
  TypeError);
¿Por qué? La idea es que el operador solo tolera omisiones deliberadas. Un valor incalculable (que no sea undefinedy null) es probablemente un error y debe informarse, en lugar de evitarse .

Cortocircuito   

En una cadena de accesos de propiedad e invocaciones de función / método, la evaluación se detiene una vez que el primer operador opcional encuentra undefinedo nullen su lado izquierdo:
function isInvoked(obj) {
  let invoked = false;
  obj?.a.b.m(invoked = true);
  return invoked;
}

assert.equal(
  isInvoked({a: {b: {m() {}}}}), true);
  
// The left-hand side of ?. is undefined
// and the assignment is not executed
assert.equal(
  isInvoked(undefined), false);
Este comportamiento difiere de un operador / función normal donde JavaScript siempre evalúa todos los operandos / argumentos antes de evaluar el operador / función. Se llama cortocircuito . Otros operadores de cortocircuito:
  • a && b
  • a || b
  • c ? t : e

Alternativas al encadenamiento opcional   

Hasta ahora, las siguientes alternativas al encadenamiento opcional se usaban en JavaScript.

&&operador   

Las siguientes dos expresiones son más o menos equivalentes:
p.address?.street?.name
p.address && p.address.street && p.address.street.name
Para cada uno a && b, bsolo se evalúa (y se devuelve) si aes verdadero. apor lo tanto, actúa como una condición o guardia para b.

Los inconvenientes de &&  

Además de la verbosidad, el uso &&tiene dos desventajas.
Primero, si falla, &&devuelve su lado izquierdo, mientras que ?.siempre devuelve undefined:
const value = null;
assert.equal(value && value.prop, null);
assert.equal(value?.prop, undefined);
Segundo, &&falla para todos los lados falsos de la izquierda, mientras que ?.solo falla undefinedy null:
const value = '';
assert.equal(value?.length, 0);
assert.equal(value && value.length, '');
Tenga en cuenta que, aquí, &&devolver su lado izquierdo es peor que en el ejemplo anterior.

Desestructuración   

En principio, también puede usar la desestructuración para manejar los accesos de propiedad encadenados. Pero no es bonito:
for (const p of persons) {
  const { address: { street: {name=undefined}={} }={} } = p;
  assert.equal(
    name,
    p.address?.street?.name);
}

Lodash get()  

La funciónget() de la biblioteca Lodash es otra alternativa al encadenamiento opcional.
Por ejemplo, las siguientes dos expresiones son equivalentes:
import {get} from 'lodash-es';

p.address?.street?.name
get(p, 'address.street.name')

Disponibilidad de encadenamiento opcional   

  • Babel tiene el complemento @babel/plugin-proposal-optional-chaining.
  • Para disponibilidad en otro lugar, consulte los documentos web de MDN .

Preguntas frecuentes   

¿Por qué hay puntos o?.[x]y f?.()?  

Las sintaxis de los siguientes dos operadores opcionales no son ideales:
obj?.[«expr»]          // better: obj?[«expr»]
func?.(«arg0», «arg1») // better: func?(«arg0», «arg1»)
Por desgracia, la sintaxis menos elegante es necesaria, porque distinguir la sintaxis ideal (primera expresión) del operador condicional (segunda expresión) es demasiado complicado:
obj?['a', 'b', 'c'].map(x => x+x)
obj ? ['a', 'b', 'c'].map(x => x+x) : []

¿Por qué null?.propevaluar undefinedy no null?  

El operador ?.se centra principalmente en su lado derecho: ¿ .propexiste la propiedad ? Si no, pare temprano. Por lo tanto, mantener información sobre su lado izquierdo rara vez es útil. Sin embargo, solo tener un único valor de “terminación anticipada” simplifica las cosas.

No hay comentarios.:

Publicar un comentario

Dejanos tu comentario para seguir mejorando!

outbrain

Páginas