Pawan Nogariya
Pawan Nogariya

Reputation: 8960

How to add getter to an existing object

I can have a getter in a JavaScript object like this:

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

I can even add more properties on the fly, like this:

member.isGuest = true;

But, is there any way we can add getters to an existing object? Something like this:

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

Upvotes: 91

Views: 28559

Answers (7)

Mohamed BEN KHOUYA
Mohamed BEN KHOUYA

Reputation: 112

Object.defineProperty(obj, prop, descriptor)

is the best solution like they say above.

what i want to add is, in order to copy getter/setter from object to other, you can use Object.create() & Object.getOwnPropertyDescriptors like this:

let obj = {
 _value: 0,
}
Object.defineProperty(obj, 'value', {
  configurable: true,
  enumerable: true,
  get() {
    return this._value;
  },
  set(val) {
    this._value = val;
  }
})
const ObjCopy = Object.create(Object.getPrototypeOf(obj),
 Object.getOwnPropertyDescriptors(obj));

This way, you will copy its properties + its getters/setters + its prototype

Upvotes: 0

YakovL
YakovL

Reputation: 8327

Moreover, you can add a custom getter and preserve the old value if it is not supposed to be calculated from other values, like in your example. To do so, create additional context layer using an anonimous function like this:

(function() {
    const oldValue = yourObject[targetProperty];
    let currentValue = oldValue;

    const getter = function() {
        return currentValue; // or do something before returning, like applying parseInt or whatever
    };
    const 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
    });
})();

Upvotes: 3

Hunter Kohler
Hunter Kohler

Reputation: 2715

For the good old purposes of completeness, Reflect.defineProperty is also an option :). Note that Object.defineProperty and Reflect.defineProperty do not behave the same.

MDN compares the two functions (as well as all similar Object and Reflect methods):

Method Name Object Reflect
defineProperty() Object.defineProperty() returns the object that was passed to the function. Returns a TypeError if the property was not successfully defined on the object. Reflect.defineProperty() returns true if the property was defined on the object and false if it was not.

I prefer Reflect because I think boolean checks make more sense, but in general remember to error handle if you think that there may be conflicts (these should be infrequent when messing with object properties, unless one of your libraries is making similar, possibly conflicting changes).

Upvotes: 0

shreyasm-dev
shreyasm-dev

Reputation: 2834

This is possible not only with the above solutions, but also using the ... operator.

// 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)

... is the spread operator, which "spreads" the contents of the object it is used on, hence the name. For example:

  • doSomething(...[1, 2, 3]) is the same as doSomething(1, 2, 3)
  • { ...{x: 1, y: 2, z: 3} } is the same as { x: 1, y: 2, z: 3 }

Upvotes: 4

daveoncode
daveoncode

Reputation: 19578

You can use the new Object.defineProperty this way:

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

In the past you had to use __defineGetter__ but now it has been deprecated.

Upvotes: 19

SmartAn
SmartAn

Reputation: 18

You can only use get and set in a Class, It's mean that getter and setter method. but you can add a function to class:

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

member.isGuest()

the get means that property can be read! the set means that property can be write! You can look it in book 《JavaScript:The.Definitive.Guide》6edition the 6 chapter!

Upvotes: -9

gurvinder372
gurvinder372

Reputation: 68393

try defineProperty

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

Upvotes: 121

Related Questions