答案(请阅读下面的答案,他们各自的作者提供了宝贵的见解):
- "writable: false" 阻止分配新值,但 Object.defineProperty 不是赋值操作,因此忽略了 "writable" 的值
- 属性属性是继承的,因此属性将在每个子类/实例上保持不可写,直到一个子类(或子类的实例)将“可写”的值更改回为真
问题:
有关属性“可写”描述符的 MDN 文档指出:
当且仅当与属性关联的值可以使用赋值运算符更改时,可写为 true。默认为假。
官方的 ECMA-262 第 6 版或多或少声明了相同的内容。含义很清楚,但据我了解,它仅限于原始属性(即该特定对象上的属性)
但是,请考虑以下示例(JSFiddle):
//works as expected, overloading complete
var Parent = function() {};
Object.defineProperty(Parent.prototype, "answer", {
value: function() { return 42; }
});
var Child = function() {};
Child.prototype = Object.create(Parent.prototype, {
answer: {
value: function() { return 0; }
}
});
var test1 = new Parent();
console.log(test1.answer()); //42
var test2 = new Child();
console.log(test2.answer()); //0
//does not work as expected
var Parent2 = function() {};
Object.defineProperty(Parent2.prototype, "answer", {
value: function() { return 42; }
});
var Child2 = function() {};
Child2.prototype = Object.create(Parent2.prototype);
test3 = new Parent2();
console.log(test3.answer()); //42
test4 = new Child2();
test4.answer = function() { return 0; };
console.log(test4.answer()); //42
按照这个例子,我们看到,虽然该属性是不可写的,但它可以在子类(test2)的原型上重载,正如我所期望的那样。
但是,当尝试在子类(test4)的实例上重载方法时,它会静默失败。我原以为它可以像 test2 一样工作。尝试重载 Parent 实例上的属性时也会发生同样的情况。
同样的事情发生在 NodeJS 和 JSFiddle 中,并且在某些情况下,实例上的重载会引发关于属性只读性质的 TypeError。
您能否向我确认这是预期的行为?如果是这样,解释是什么?