I created a read only property on an object and the appropriate unit tests.
//works as expected
function OnSelf() {
this._val = 'test';
Object.defineProperty(this, 'test', {
enumerable: true,
configurable: false,
get: function () {
return this._val;
}
});
}
However, I realized that I should have been putting the readonly property on the prototype instead of each individual instance. I changed my code and then one of my tests failed.
//no exception when trying to delete the property
function OnPrototype() {
this._val = 'test';
}
Object.defineProperty(OnPrototype.prototype, 'test', {
enumerable: true,
configurable: false,
get: function () {
return this._val;
}
});
It appears that when deleting a read-only property on the prototype, no exception is thrown, but when the property is on the object, an exception is thrown.
var s = new OnSelf();
delete s.test; // throws error
var p = new OnPrototype();
delete p.test; // doesn't delete it, but no error occurs
I created http://jsfiddle.net/pdgreen/3BGfM/ to demonstrate the problem. I confirmed the same behavior on Mac with chrome and firefox.
Is this the correct thing to happen? Why if the property is on the object, an exception is thrown, but on the prototype, no exception? This surprises me. Can anyone explain why it is so?
That's the correct behavior you're seeing. The 'delete' keyword only deletes an object's own properties; it can't delete the object's prototype's properties. (And if it did, that would be terrible -- it would mess up any other objects inheriting from that same prototype!)
Try the following:
> function Constructor() {}
undefined
> Constructor.prototype.test = "Prototype";
"Prototype"
> var obj = new Constructor();
undefined
> obj.test
"Prototype"
> obj.test = "Child"
"Child"
> obj.test
"Child"
> delete obj.test
true
> obj.test
"Prototype"
The key to prototypical inheritance is that prototypes are actual objects containing their own properties, and that inheritance is fully live and dynamic. If an object doesn't define a property but an object in its prototype chain does, the child object inherits that value. When its value gets overridden locally, it now defines that property itself. If the child object's property gets deleted, the value from the prototype comes through again.