我发现ES2015类阻止设置(重新定义)他们的原型。
通常声称ES2015类只是ES5构造函数和基于原型的继承之上的“语法糖”。
但这是行为的差异......
此行为是ES2015规范的一部分吗?我没有找到任何关于此的文件...
以下示例说明了不同之处:
function Pet() {}
Pet.prototype.eat = () => {
console.log('Pet is eating ...');
}
Pet.prototype = {eat: function(){console.log('Pet is REALLY eating ...')}};
const pet = new Pet();
pet.eat(); // -> Pet is REALLY eating ...
console.log(Object.getOwnPropertyDescriptor(Pet, 'prototype'));
=> 重新定义宠物作品的原型
class Pet {
eat() {
console.log('Pet is eating ...');
}
}
Pet.prototype = {eat: function(){console.log('Pet is REALLY eating ...')}};
const pet = new Pet();
pet.eat(); // -> Pet is eating ...
console.log(Object.getOwnPropertyDescriptor(Pet, 'prototype'));
=> 重新定义宠物原型不起作用
任何有关此行为文档的指示都将不胜感激......
答案 0 :(得分:7)
这里的不同之处在于,使用class
创建时,prototype
对象设置为writable: false
,因此您无法通过分配替换Pet.prototype
。删除严格模式时,您可以在Object.getOwnPropertyDescriptor()
调用中看到差异。
OP的第一个代码示例显示了这一点:
{
...
"writable": true,
"enumerable": false,
"configurable": false
}
OP的第二个代码示例显示了这一点:
{
...
"writable": false,
"enumerable": false,
"configurable": false
}
writable
属性确定是否可以为属性Pet.prototype
分配新值(例如,用新对象替换)。 false
值意味着您无法使用分配替换Pet.prototype
。因此,当您的代码尝试执行此操作时,它会失败。
您仍然可以在原型对象中添加或删除单个属性,而不是替换整个对象。这对我来说是有意义的,因为替换整个原型对象会撤消整个class
定义。如果您有真正的理由替换它,您可以将Pet.prototype
对象更改为可写。
这在ES 2015规范中有所描述。在14.5.14 Runtime Semantics: ClassDefinitionEvaluation中,在步骤16中,它执行此操作:
- 执行MakeConstructor(F,false,proto)。
醇>
false
参数使得创建的原型不可写(因此无法替换)。
而且,如果你再看9.2.8 MakeConstructor(),你会在第6步看到这个:
让状态为DefinePropertyOrThrow(F," prototype",PropertyDescriptor {[[Value]]:prototype,[[Writable]]:writablePrototype,[[Enumerable]]:false,[[Configurable]] :false})。
writable
属性获取之前传递给它的false
值。
人们经常声称,ES2015课程只是"语法糖"在ES5构造函数和基于原型的继承之上。 但这是行为的差异......
虽然class
中定义的方法的一般操作几乎相同,但另一个答案描述了使用class
与手动分配原型之间的其他几个差异:In javascript, what are the differences between a class and a constructor?