javascript - ES2015 类阻止设置原型(prototype)

标签 javascript ecmascript-6 es6-class

我发现 ES2015 类阻止设置(重新定义)它们的原型(prototype)。

人们经常声称 ES2015 类只是 ES5 构造函数和基于原型(prototype)的继承之上的“语法糖”。
但这是行为上的差异......

这种行为是 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'));

=> 重新定义宠物作品原型(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'));

=> 重新定义 Pet 的原型(prototype)不起作用

任何指向此行为文档的指针都将不胜感激......

最佳答案

这里的区别在于,当使用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。因此,当您的代码尝试这样做时,它会失败。

您仍然可以自由地在原型(prototype)对象中添加或删除单个属性,只是不能替换整个对象。这对我来说有些意义,因为替换整个原型(prototype)对象会撤消整个 class 定义。如果您有现实世界的理由替换它,您可能会将 Pet.prototype 对象更改为可写。

这在 ES 2015 规范中有描述。在 14.5.14 Runtime Semantics: ClassDefinitionEvaluation ,在第 16 步,它这样做:

  1. Perform MakeConstructor(F, false, proto).

false 参数使创建的原型(prototype)不可写(因此无法替换)。

然后,如果你再看看 9.2.8 MakeConstructor() ,您会在第 6 步中看到:

Let status be DefinePropertyOrThrow(F, "prototype", PropertyDescriptor{[[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false}).

writable 属性获取先前传递给它的 false 值。


It is often claimed that ES2015 classes are just "syntactic sugar" on top of ES5 constructor functions and prototype based inheritance. But this is a difference in behavior...

虽然 class 中定义的方法的一般操作几乎相同,但另一个答案描述了使用 class 与手动分配给原型(prototype)之间的其他几个区别: In javascript, what are the differences between a class and a constructor?

关于javascript - ES2015 类阻止设置原型(prototype),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50543757/

相关文章:

javascript - 导出默认值有效,但在 React 中导出任何其他内容都不起作用

javascript - ES6 类中的构造函数和原型(prototype)中的构造函数之间的区别?

reactjs - 错误: Minified React error #130

javascript - Angular $routeProvider - 以编程方式添加路由解析

javascript - 如果 javascript 语句有问题

javascript - 在一个 js 文件中预编译所有 handlebars 模板文件时出错

javascript - ES6 Promises 和类属性

javascript - 在 Javascript 中使用 Maps 实现二维数组

javascript - 如何使两个不同的组件具有相同的高度

javascript - 如何在 JavaScript 中从字符串实例化类