Command Palette

Search for a command to run...

Reflect.get(), set() y has() en JavaScript

Aprende a manipular propiedades de objetos usando los métodos fundamentales de Reflect API para operaciones de metaprogramación más limpias.

Lectura: 12 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • Reflect.get() obtiene el valor de una propiedad con control sobre el receptor
  • Reflect.set() modifica propiedades y retorna un booleano indicando éxito
  • Reflect.has() verifica si una propiedad existe en un objeto
  • Estos métodos son más consistentes que los operadores de punto y corchetes
  • Son esenciales para implementar traps de Proxy (get, set y has)

Introducción

Los métodos Reflect.get(), Reflect.set() y Reflect.has() son las herramientas fundamentales de la API Reflect para manipular propiedades de objetos. Proporcionan una alternativa más consistente y controlable a los operadores tradicionales de punto (.) y corchetes ([]), especialmente útil en escenarios de metaprogramación.

A diferencia de los operadores tradicionales, estos métodos de Reflect siempre retornan valores predecibles: Reflect.get() retorna el valor de la propiedad o undefined, Reflect.set() retorna un booleano indicando si la operación fue exitosa, y Reflect.has() retorna un booleano indicando si la propiedad existe. Esta consistencia hace el código más robusto y fácil de depurar.

Correspondencia con Proxy

Los métodos Reflect.get(), Reflect.set() y Reflect.has() corresponden directamente a los traps get, set y has de Proxy. Esta relación es fundamental cuando implementas Proxies que interceptan operaciones de propiedades.

Reflect.get()

Reflect.get() obtiene el valor de una propiedad de un objeto. A diferencia del operador de punto o corchetes, Reflect.get() te permite especificar un receptor explícito que controla el valor de this cuando la propiedad es un getter.

Sintaxis y Uso Básico

La firma de Reflect.get() es: Reflect.get(target, propertyKey, receiver). El primer parámetro es el objeto objetivo, el segundo es el nombre de la propiedad, y el tercero (opcional) es el receptor que se usará como this en getters.

reflect-get-basico.js
Loading code...

Este ejemplo muestra cómo Reflect.get() funciona de manera similar a los operadores tradicionales para obtener propiedades simples. Sin embargo, el poder real de Reflect.get() se manifiesta cuando trabajas con getters y necesitas controlar el contexto de this.

Receptor explícito

El parámetro receiver es opcional pero muy importante. Cuando no se especifica, el receptor es el mismo objeto target. Cuando se especifica, se usa como this en getters, lo que te permite controlar el contexto de ejecución.

Reflect.get() con Getters

Cuando una propiedad es un getter, el valor de this dentro del getter depende del receptor. Reflect.get() te permite controlar este comportamiento explícitamente, algo que no es posible con los operadores de punto o corchetes.

reflect-get-getters.js
Loading code...

Este ejemplo muestra cómo el receptor afecta el valor de this dentro de un getter. Cuando usamos objeto2 como receptor, el getter usa las propiedades de objeto2 para calcular el valor, incluso aunque estamos obteniendo la propiedad de objeto1.

Reflect.set()

Reflect.set() establece el valor de una propiedad en un objeto y retorna un booleano indicando si la operación fue exitosa. A diferencia de los operadores de asignación, Reflect.set() siempre retorna un valor, lo que facilita el manejo de errores y la validación.

Sintaxis y Uso Básico

La firma de Reflect.set() es: Reflect.set(target, propertyKey, value, receiver). El primer parámetro es el objeto objetivo, el segundo es el nombre de la propiedad, el tercero es el valor a establecer, y el cuarto (opcional) es el receptor que se usará como this en setters.

reflect-set-basico.js
Loading code...

Este ejemplo muestra cómo Reflect.set() retorna un booleano indicando si la operación fue exitosa. Esto es útil para validar si la asignación se completó correctamente, especialmente cuando trabajas con objetos que pueden ser no extensibles o propiedades no configurables.

Propiedades no configurables

Si intentas modificar una propiedad no configurable o agregar una propiedad a un objeto no extensible, Reflect.set() retornará false en modo estricto. Los operadores de asignación lanzarían un error, lo que hace que Reflect.set() sea más manejable en estos casos.

Reflect.set() con Setters

Cuando una propiedad es un setter, el valor de this dentro del setter depende del receptor. Reflect.set() te permite controlar este comportamiento explícitamente, lo que es útil cuando necesitas ejecutar setters en el contexto de un objeto diferente.

reflect-set-setters.js
Loading code...

Este ejemplo muestra cómo el receptor afecta el comportamiento de un setter. Cuando usamos objeto2 como receptor, el setter modifica las propiedades de objeto2, incluso aunque estamos estableciendo la propiedad en objeto1.

Reflect.has()

Reflect.has() verifica si una propiedad existe en un objeto, ya sea como propiedad propia o heredada. Es equivalente al operador in, pero con una sintaxis más consistente con el resto de la API Reflect.

Sintaxis y Uso Básico

La firma de Reflect.has() es: Reflect.has(target, propertyKey). El primer parámetro es el objeto objetivo y el segundo es el nombre de la propiedad a verificar. Retorna true si la propiedad existe y false en caso contrario.

reflect-has-basico.js
Loading code...

Este ejemplo muestra cómo Reflect.has() funciona de manera equivalente al operador in. La ventaja de Reflect.has() es que proporciona una sintaxis consistente con el resto de la API Reflect y es especialmente útil en metaprogramación.

Propiedades propias vs heredadas

Reflect.has() retorna true tanto para propiedades propias como heredadas. Si necesitas verificar solo propiedades propias, usa Object.prototype.hasOwnProperty.call(obj, prop) o Object.hasOwn() (ES2022).

Casos Especiales y Errores Comunes

Al trabajar con Reflect.get(), Reflect.set() y Reflect.has(), hay varios casos especiales y errores comunes que debes conocer para evitar bugs difíciles de rastrear.

  • <strong>Objetos no extensibles:</strong> Reflect.set() retorna false si intentas agregar propiedades a objetos no extensibles.
  • <strong>Propiedades no configurables:</strong> No puedes modificar propiedades no configurables con Reflect.set().
  • <strong>Propiedades solo lectura:</strong> Reflect.set() retorna false si intentas modificar propiedades con writable: false.
  • <strong>Propiedades heredadas:</strong> Reflect.has() retorna true para propiedades heredadas del prototipo.
  • <strong>Propiedades Symbol:</strong> Reflect.get(), set() y has() funcionan con propiedades Symbol igual que con string.

Estos casos son especialmente importantes cuando trabajas con Proxies, ya que los traps interceptan todas las operaciones de propiedades y debes manejar correctamente los casos edge.

reflect-get-set-has-casos.js
Loading code...

Este ejemplo muestra varios casos especiales como objetos no extensibles, propiedades no configurables y propiedades solo lectura. Reflect.set() retorna false en estos casos en lugar de lanzar un error, lo que facilita el manejo de estas situaciones.

Modo estricto

En modo estricto, intentar asignar a una propiedad no configurable o agregar una propiedad a un objeto no extensible lanzará un TypeError. Reflect.set() evita esto al retornar false, lo que te permite manejar el error de manera controlada.

Resumen: Reflect.get(), set() y has()

Conceptos principales:

  • Reflect.get() obtiene propiedades con control sobre el receptor
  • Reflect.set() modifica propiedades y retorna booleano de éxito
  • Reflect.has() verifica existencia de propiedades propias y heredadas
  • El receptor controla el valor de this en getters y setters
  • Son más consistentes que operadores tradicionales en metaprogramación

Mejores prácticas:

  • Usa estos métodos dentro de traps de Proxy para mantener comportamiento por defecto
  • Especifica el receptor cuando necesites controlar el contexto de this
  • Verifica el retorno de Reflect.set() para detectar asignaciones fallidas
  • Usa Object.hasOwn() para verificar solo propiedades propias
  • Prefiere estos métodos sobre operadores en código de metaprogramación