Cómo agregar getter a un objeto existente

4 minutos de lectura

avatar de usuario
Pawan Nogariya

Puedo tener un getter en un objeto JavaScript como este:

var member = {
    firstName:"XYZ", 
    lastName:"zzz", 
    get fullName(){ return (this.firstName + ' ' + this.lastName); }
}

Incluso puedo agregar más propiedades sobre la marcha, como esta:

member.isGuest = true;

Pero, ¿hay alguna manera de que podamos agregar captadores a un objeto existente? Algo como esto:

member.isGuest = get isGuest(){ return this.firstName=='Guest'; }

probar defineProperty

Object.defineProperty(member, 'isGuest', {
  get: function() { return this.firstName=='Guest' }
});

  • Creo que un problema con la solución anterior es si usara Object.assign en el member objeto, el getter no se copiará como lo haría si se estableciera durante la creación del objeto y no está definido. jsfiddle.net/ygd20ws4

    – usuario1331784

    26 de abril de 2018 a las 13:14

  • @ user1331784 esto se debe a que la propiedad creada no es enumerable de forma predeterminada. Puede establecer la clave enumerable en la descripción en verdadero y Object.assign copiará el getter.

    – boorg

    10 mayo 2018 a las 11:33

  • En realidad con la clave enumerable no se copiará el captador sino el valor en el momento de la copia.

    – boorg

    10 mayo 2018 a las 16:41

avatar de usuario
daveoncode

Puedes usar el nuevo Objeto.defineProperty Por aquí:

Object.defineProperty(
    member, 
    'prop', 
    {
        get: function() { 
            return this.lastName.toUpperCase()
        }
    }
);

En el pasado tenías que usar __defineGetter__ pero ahora ha quedado en desuso.

  • Te mereces un voto positivo por un fracaso de FGITW. (¡En realidad tienes más contenido!)

    – wizzwizz4

    17 de julio de 2016 a las 12:25

Esto es posible no solo con las soluciones anteriores, sino también con el ... operador.

// Initialize x
var x = {
  x: 5
}

// Log x.x and x.y
console.log(x.x, x.y /* undefined */)

x = {
  ...x, // {...x} is the same as {x: x.x}
  
  // The getter
  get y() {
    return this.x
  }
}

// Log x.x and x.y
console.log(x.x, x.y /* Not undefined */)

// Set x.x to 1234
x.x = 1234

// Log x.x and x.y
console.log(x.x, x.y)

... es el operador de propagación, que “difunde” el contenido del objeto en el que se usa, de ahí el nombre. Por ejemplo:

  • doSomething(...[1, 2, 3]) es lo mismo que doSomething(1, 2, 3)
  • { ...{x: 1, y: 2, z: 3} } es lo mismo que { x: 1, y: 2, z: 3 }

  • Esto, en realidad, copia superficialmente el objeto existente en un nuevo objeto con un captador adicional. Código más limpio. Pero no funciona si no puede configurar el objeto al que desea agregar el getter (por ejemplo, un objeto singleton/factory)

    – TamusJRoyce

    8 de diciembre de 2020 a las 12:12

Además, puede agregar un captador personalizado y conservar el valor anterior si no se supone que se calcule a partir de otros valores, como en su ejemplo. Para hacerlo, cree una capa de contexto adicional usando una función anónima como esta:

(function(){
    var oldValue = yourObject[targetProperty];
    var currentValue = oldValue;
    var getter = function() {
        return currentValue; // or do something before returning, like applying parseInt or whatever
    };
    var setter = function(newValue) {
        currentValue = newValue; // or add some customization as well
    };
    Object.defineProperty(yourObject,targetProperty,{
        get: getter,
        set: setter,
        enumerable: true, // depending on your needs
        configurable: true // depending on your needs
    });
})();

Para los buenos viejos propósitos de la integridad, Reflect.defineProperty también es una opción :). Tenga en cuenta que Object.defineProperty y Reflect.defineProperty no te comportes igual.

MDN compara las dos funciones (así como todos los similares Object y Reflect métodos):

Nombre del método Object Reflect
defineProperty() Object.defineProperty() devuelve el objeto que se pasó a la función. Devuelve un TypeError si la propiedad no se definió correctamente en el objeto. Reflect.defineProperty() devoluciones true si la propiedad se definió en el objeto y false si no fuera así.

yo prefiero Reflect porque creo que las comprobaciones booleanas tienen más sentido, pero en general recuerda manejar los errores si crees que puede haber conflictos (estos deberían ser poco frecuentes cuando se juega con las propiedades del objeto, a menos que una de sus bibliotecas esté haciendo cambios similares, posiblemente conflictivos).

avatar de usuario
SmartAn

Solo puede usar get y set en una clase, es decir, el método getter y setter. pero puedes agregar una función a la clase:

member.isGuest = function isGuest(){ return this.firstName=='Guest';}

member.isGuest()

¡get significa que la propiedad se puede leer! ¡el conjunto significa que la propiedad se puede escribir! Puede buscarlo en el libro 《JavaScript: The.Definitive.Guide》6edition the 6 chapter!

¿Ha sido útil esta solución?