Search code examples
javascriptgetter-setterpolyfills

Object.prototype.__defineGetter__ (and __defineSetter__) polyfill


I know the __defineGetter__ (and __defineSetter__) method name is really weird and deprecated but I find it more convenient than Object.defineProperty. Compare yourself:

//Readable
Something.prototype.__defineGetter__("name", function() {return this._name;});
//Uh... - what?
Object.defineProperty(Something.prototype, "name", {
                       get: function() {return this._name;}
                     });

Because, as I said, this method is being deprecated. So I'm creating a polyfill to put it back in bussiness:

if(!Object.prototype.__defineGetter__) {
  Object.prototype.__defineGetter__ = function(name, func) {
    Object.defineProperty(this, name, {
      get: func
    });
  }
}

It really just calls the standard Object.defineProperty. I could name the __defineGetter__ whatever I wanted. I just decided to stick to something that already existed.

The problem here is that if I use __defineGetter__ and __defineSetter__ polyfills on the same property, I'm calling Object.defineProperty twice.

My question is: Is it OK to call Object.defineProperty twice on same property? Doesn't it overwrite something for example?


Solution

  • To retain the old set or get when calling defineProperty again, you'll have to pull them out when adding the getter or setter:

    var proto = Object.prototype;
    
    proto.__defineGetter__ = proto.__defineGetter__ || function(name, func) {
        var descriptor = Object.getOwnPropertyDescriptor(this, name);
        var new_descriptor = { get: func, configurable: true};
        if (descriptor) {
            console.assert(descriptor.configurable, "Cannot set getter");
            if (descriptor.set) new_descriptor.set = descriptor.set; // COPY OLD SETTER
        }
        Object.defineProperty(this, name, new_descriptor);
    };
    
    proto.__defineSetter__ = proto.__defineSetter__ || function(name, func) {
        var descriptor = Object.getOwnPropertyDescriptor(this, name);
        var new_descriptor = { set: func, configurable: true};
        if (descriptor) {
            console.assert(descriptor.configurable, "Cannot set setter");
            if (descriptor.get) new_descriptor.get = descriptor.get; // COPY OLD GETTER
        }
        Object.defineProperty(this, name, new_descriptor);
    };