问题
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