我在对象上创建了一个只读属性,并进行了相应的单元测试。
//works as expected
function OnSelf() {
this._val = 'test';
Object.defineProperty(this, 'test', {
enumerable: true,
configurable: false,
get: function () {
return this._val;
}
});
}
然而,我意识到我应该将readonly属性放在原型而不是每个单独的实例上。我改变了我的代码,然后我的一个测试失败了。
//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;
}
});
当删除原型上的只读属性时,似乎不会抛出异常,但是当属性在对象上时,会抛出异常。
var s = new OnSelf();
delete s.test; // throws error
var p = new OnPrototype();
delete p.test; // doesn't delete it, but no error occurs
我创建了http://jsfiddle.net/pdgreen/3BGfM/来证明问题。我在Mac上使用chrome和firefox确认了相同的行为。
这是正确的事吗?为什么如果属性在对象上,抛出异常,但在原型上,没有异常?这让我感到惊讶。谁能解释为什么会这样呢?
答案 0 :(得分:4)
这是你所看到的正确行为。 'delete'关键字只删除对象自己的属性;它无法删除对象的原型属性。 (如果确实如此,那将是非常糟糕的 - 它会搞砸从同一原型继承的任何其他对象!)
尝试以下方法:
> 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"
原型继承的关键是原型是包含自己属性的实际对象,并且继承是完全实时和动态的。如果对象没有定义属性但其原型链中的对象确实存在,则子对象继承该值。当它的值在本地被覆盖时,它现在定义了该属性本身。如果子对象的属性被删除,原型中的值将再次出现。
答案 1 :(得分:1)
当直接在对象上定义属性时,该对象具有可以删除的“自己”属性。但是,如果在原型上定义了属性,则没有要删除的“自己”属性,因此删除操作是无操作。该属性在原型上实际上是 (这就是原型继承的工作方式,除非更改了属性,否则该属性实际上不会添加到对象中。)
弄清楚这是一段扭曲的迷宫般的迷宫......也被称为ES5规范,但关键部分(在解码之后)是8.12.7,同时意识到{ {1}}该部分讨论的内部方法将在原型案例中返回GetOwnProperty
。