ES2015类会阻止设置原型

时间:2018-05-26 14:27:00

标签: javascript ecmascript-6 es6-class

我发现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'));

=> 重新定义宠物原型不起作用

任何有关此行为文档的指示都将不胜感激......

1 个答案:

答案 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中,它执行此操作:

  
      
  1. 执行MakeConstructor(F,false,proto)。
  2.   

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?