Object.prototype.__defineGetter__ (and __defineSetter__) polyfill

南楼画角 提交于 2020-01-04 06:23:12

问题


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?


回答1:


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);
};



回答2:


So you don't like using defineProperty, which is fine. However, then why even bother using __defineGetter__ and __defineSetter__? In my opinion, that looks even worse.

Back in March 2013 I had the same problem with emetic code, which is why I cooked up a simple 41 LOC micro-library which you can install via the command:

npm install dictionary

Using this micro library you can define getters and setters like this instead:

Something.prototype.define({
    get name() {
        return this._name;
    },
    set name(_name) {
        this._name = _name;
    }
});

In addition it also allows you to create non-enumerable, non-deletable and constant properties easily. Read the documentation for more details.

If you don't want these additional features then just use:

Object.prototype.define = function (properties) {
    if (Object.isExtensible(this)) {
        var ownDescriptor = Object.getOwnPropertyDescriptor;
        var defineProperty = Object.defineProperty;
        var keys = Object.keys(properties);
        var length = keys.length;
        var index = 0;

        while (index < length) {
            var key = keys[index++];
            var descriptor = ownDescriptor(properties, key);
            defineProperty(this, key, descriptor);
        }
    }
};

Hope that helps.



来源:https://stackoverflow.com/questions/27400010/object-prototype-definegetter-and-definesetter-polyfill

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!