W3docs

Descriptores de propiedades en JavaScript

Aprende cómo funcionan los flags de propiedad (writable, enumerable, configurable) y los descriptores en JavaScript, incluyendo defineProperty, freeze, seal y modo estricto.

Los flags y descriptores de propiedades de JavaScript ofrecen un control preciso sobre las propiedades de los objetos, lo que permite desarrollar aplicaciones robustas y seguras. Este artículo explora estas características en detalle, con ejemplos prácticos de código para ayudarte a gestionar el comportamiento de las propiedades de forma efectiva.

Entendiendo los atributos de propiedades en JavaScript

Los objetos de JavaScript son colecciones de propiedades, y cada propiedad tiene atributos asociados que definen su comportamiento. Estos atributos, comúnmente llamados flags de propiedad, incluyen:

  • Writable: Determina si el valor de la propiedad puede cambiarse.
  • Enumerable: Controla si la propiedad es visible durante la enumeración, como en un bucle for...in.
  • Configurable: Especifica si la propiedad puede eliminarse o modificarse.

Estos flags son fundamentales para controlar el acceso a las propiedades de los objetos, garantizar la integridad de los datos e implementar encapsulación en aplicaciones JavaScript.

Explorando los descriptores de propiedades

Los descriptores de propiedades proporcionan información detallada sobre la propiedad de un objeto, encapsulando su valor y sus flags. Se recuperan con Object.getOwnPropertyDescriptor(obj, propName) y se establecen con Object.defineProperty(obj, propName, descriptor). Un objeto descriptor de propiedad puede contener:

  • value: El valor asociado a la propiedad.
  • writable: Indica si el valor de la propiedad puede cambiarse.
  • enumerable: Indica si la propiedad es enumerable.
  • configurable: Determina si el descriptor de la propiedad puede modificarse y si la propiedad puede eliminarse del objeto.

Nota: Cuando creas una propiedad de la forma habitual (user.name = "John"), los tres flags se establecen en true. Pero al definir una propiedad nueva mediante Object.defineProperty, cualquier flag no especificado tiene como valor predeterminado false.


javascript— editable

Object.getOwnPropertyDescriptor solo examina las propiedades propias del objeto. Si solicitas una propiedad que el objeto hereda de su prototipo (o una propiedad que no existe), devuelve undefined.


javascript— editable

Para saber más sobre cómo los objetos heredan propiedades, consulta Herencia prototípica.

Descriptores de datos vs. descriptores de acceso

Hasta ahora hemos descrito los descriptores de datos, que almacenan un value junto con el flag writable. JavaScript también admite descriptores de acceso, que sustituyen value/writable por funciones getter y setter:

  • get: una función que se llama cuando se lee la propiedad (no recibe argumentos).
  • set: una función que se llama cuando se asigna un valor a la propiedad (recibe el nuevo valor).

Un descriptor es o bien un descriptor de datos o bien un descriptor de acceso — nunca ambos. Combinar value/writable con get/set lanza un error. Ambos tipos comparten los flags enumerable y configurable.

Las propiedades de acceso permiten calcular un valor al leer o validarlo al escribir. En el siguiente ejemplo, exponemos un accessor fullName respaldado por dos propiedades de datos:


javascript— editable

Para un tratamiento más completo de la sintaxis get/set (incluyendo la forma abreviada dentro de literales de objeto), consulta Getters y setters de propiedades. Dado que los getters y setters se ejecutan con this enlazado al objeto, también es útil entender Métodos de objeto y "this".

Definir y leer múltiples propiedades a la vez

Para trabajar con varias propiedades en un solo paso, JavaScript proporciona los equivalentes plurales de los métodos anteriores:

  • Object.defineProperties(obj, descriptors) define múltiples propiedades a partir de un mapa de descriptores.
  • Object.getOwnPropertyDescriptors(obj) devuelve los descriptores de todas las propiedades propias (incluidas las no enumerables y las claves symbol) como un único object.

Object.getOwnPropertyDescriptors es especialmente útil para clonar un objeto con sus flags — un spread simple o Object.assign copia los valores pero restablece todos los flags a true y omite los accessors.


javascript— editable

Manipulación de flags de propiedades

Comprender y manipular los flags de propiedades es fundamental para un desarrollo efectivo en JavaScript. Veamos cómo controlar estos flags para ajustar el comportamiento de las propiedades.

Hacer una propiedad no escribible

Impedir modificaciones en una propiedad garantiza la coherencia de los datos. Esto se consigue estableciendo el flag writable en false.


javascript— editable

El comportamiento de la asignación fallida depende del modo en que se ejecute el código. En modo no estricto, escribir en una propiedad no escribible falla silenciosamente: la asignación simplemente se ignora, no se lanza ningún error y la ejecución continúa — lo que puede ocultar errores. En modo estricto ("use strict", y el valor predeterminado dentro de módulos ES y cuerpos de clase), la misma asignación lanza un TypeError. Esta regla se aplica a cualquier operación que viole un flag: eliminar una propiedad no configurable o agregar una propiedad a un objeto no extensible también falla silenciosamente en modo no estricto y lanza una excepción en modo estricto.


javascript— editable

Ocultar una propiedad de la enumeración

A veces es necesario ocultar propiedades de los procesos de enumeración, como los bucles for...in. Esto se consigue estableciendo el flag enumerable en false.


javascript— editable

Evitar la eliminación y modificación de propiedades

Para garantizar que una propiedad siga siendo una parte constante de un objeto, establece el flag configurable en false.


javascript— editable

Marcar una propiedad como no configurable es una operación irreversible — no existe ningún flag para volver a hacerla configurable, y ya no es posible cambiar enumerable ni convertir la propiedad entre un descriptor de datos y uno de acceso.

No obstante, hay dos excepciones importantes cuando una propiedad es no configurable:

  • Puedes cambiar writable de true a false (pero no de false a true).
  • Si la propiedad sigue siendo writable: true, puedes cambiar su value — ya sea mediante asignación directa o mediante Object.defineProperty.

En otras palabras, configurable: false bloquea la forma de la propiedad, pero no necesariamente su valor. Para congelar verdaderamente el valor de una propiedad, establece tanto configurable: false como writable: false.


javascript— editable

APIs de alto nivel basadas en estos flags

Raramente necesitas establecer flags propiedad por propiedad. JavaScript incluye tres métodos integrados que modifican estos flags en todo un objeto:

  • Object.preventExtensions(obj) — impide que se añadan nuevas propiedades. Las propiedades existentes aún pueden cambiarse o eliminarse.
  • Object.seal(obj) — impide añadir y eliminar propiedades marcando todas las propiedades existentes como configurable: false. Los valores aún pueden cambiar.
  • Object.freeze(obj) — el más estricto: sella el objeto y establece todas las propiedades como writable: false, de modo que nada puede añadirse, eliminarse ni modificarse.

Cada método tiene una comprobación equivalente: Object.isExtensible, Object.isSealed y Object.isFrozen. Ten en cuenta que operan a un solo nivel — Object.freeze no congela los objetos anidados (es un congelamiento "superficial").


javascript— editable

Conclusión

Los flags y descriptores de propiedades te ofrecen un control preciso sobre el comportamiento de las propiedades de los objetos:

  • Un descriptor de datos combina un value con writable; un descriptor de acceso usa funciones get/set en su lugar. Ambos comparten enumerable y configurable.
  • Lee los flags con Object.getOwnPropertyDescriptor (una propiedad) o Object.getOwnPropertyDescriptors (todas las propiedades propias); escríbelos con Object.defineProperty o Object.defineProperties. Las propiedades heredadas o inexistentes devuelven undefined.
  • configurable: false es irreversible y bloquea la forma de la propiedad, aunque una propiedad que siga siendo writable puede tener su valor modificado y su flag writable desactivado.
  • Violar un flag falla silenciosamente en modo no estricto, pero lanza un TypeError en modo estricto.
  • Usa Object.freeze, Object.seal y Object.preventExtensions cuando quieras bloquear un objeto completo en lugar de flags individuales.

Próximos pasos: explora Getters y setters de propiedades para conocer la sintaxis de los accessors, Métodos de objeto y "this" para entender cómo se comporta this dentro de ellos, y Herencia prototípica para ver cómo la búsqueda de propiedades recorre la cadena de prototipos.

Práctica

Práctica
En JavaScript, ¿cuáles son las características que pueden definirse mediante descriptores de propiedades?
En JavaScript, ¿cuáles son las características que pueden definirse mediante descriptores de propiedades?
Was this page helpful?