JS: Objetos

Teoría: Comprobación de la existencia de una propiedad

Cuando trabajamos con objetos en JavaScript, a veces necesitamos verificar si una propiedad existe antes de usar su valor. Si la propiedad no existe, podemos ejecutar una lógica especial, por ejemplo, asignarle un valor inicial.

El método más común para hacer esta verificación es comparando con undefined, pero esta técnica no es del todo confiable en ciertos casos.

Verificar propiedades en Objetos

🍏🍌🍍 Imagina que queremos contar la cantidad de veces que aparecen ciertas frutas en una lista. Si representamos el resultado en un objeto, nuestro objetivo es tener algo como esto:

const bag = [
  'manzana', 'plátano', 'pera',
  'albaricoque', 'manzana', 'plátano',
  'manzana', 'naranja', 'pera',
];

const result = {
  manzana: 3,
  plátano: 2,
  pera: 2,
  naranja: 1,
  albaricoque: 1,
};

Podríamos recorrer la lista de frutas e ir agregando cada una al objeto de resultados. Si la fruta ya existe en el objeto, aumentamos su contador; si no, la inicializamos en 1.

const contarFrutas = (frutas) => {
  const resultado = {};

  for (const nombre of frutas) {
    // Verificar existencia
    if (resultado[nombre] === undefined) {
      resultado[nombre] = 1;
    } else {
      resultado[nombre] += 1;
    }
  }

  return resultado;
};

En este caso, comparar con undefined funciona bien porque estamos seguros de que los valores serán números al contar, y ningún valor existente será undefined.

Sin embargo, este método no es del todo confiable cuando los valores pueden ser undefined por otras razones. Observemos el siguiente caso:

const obj = {
  key: hacerAlgo(),
};

Si hacerAlgo() devuelve undefined, entonces obj.key existirá en el objeto, pero tendrá el valor undefined.
Esto haría que nuestra verificación (if (resultado[nombre] === undefined)) no funcione como esperábamos.

Uso de Object.hasOwn()

Para una verificación más segura, podemos usar el método Object.hasOwn(). Este método indica si un objeto tiene una propiedad sin verificar su valor.

const contarFrutas = (frutas) => {
  const resultado = {};

  for (const nombre of frutas) {
    // Verificar existencia usando Object.hasOwn()
    if (Object.hasOwn(resultado, nombre)) {
      resultado[nombre] += 1;
    } else {
      resultado[nombre] = 1;
    }
  }

  return resultado;
};

Con esta técnica, evitamos problemas con valores undefined que podrían haber sido asignados explícitamente.

Operador de Fusión Nula (??)

Podemos mejorar aún más nuestro código usando el operador de fusión nula (??). Este operador permite definir un valor por defecto cuando una variable es null o undefined.

Ejemplo:

let valor;

valor ?? 'wow'; // 'wow'

valor = null;
valor ?? 'wow'; // 'wow'

valor = true;
valor ?? 'wow'; // true

En nuestro caso, queremos contar cada fruta, y siempre esperamos un número como valor. En lugar de hacer una verificación manual, podemos asignarle un valor por defecto de 0 usando ??.

const contarFrutas = (frutas) => {
  const resultado = {};

  for (const nombre of frutas) {
    resultado[nombre] = (resultado[nombre] ?? 0) + 1;
  }

  return resultado;
};

¿Por qué Funciona?

  • Si resultado[nombre] ya tiene un valor (como 1, 2, etc.), se usa ese número y se le suma 1.
  • Si resultado[nombre] es undefined, se usa 0 como valor predeterminado y luego se le suma 1.

Este enfoque hace que el código sea más limpio y conciso.


Resumen

  • Comparar con undefined no siempre es una forma confiable de verificar la existencia de una propiedad.
  • Usar Object.hasOwn(obj, propiedad) es una forma más segura y precisa de verificar si una propiedad existe en un objeto.
  • El operador de fusión nula (??) permite asignar valores predeterminados cuando una variable es null o undefined, ayudando a escribir código más claro y eficiente.
  • En el problema de contar frutas, resultado[nombre] = (resultado[nombre] ?? 0) + 1; ofrece una solución más simple y elegante que incluir una verificación manual.

Completado

0 / 13