我尝试ES6语法,发现我不能在类定义中定义原型属性或示例属性,为什么禁止它?
我之前用的是MyClass.prototype.prop=1
,尝试ES7的babel编译器如下,还是不能定义prototype属性。
class MyClass{
prop=1;
static sProp=1;
}
我不认为定义示例属性有任何危险,在我自己的浏览器游戏中有2种情况需要原型属性:
1.子类示例需要从基类继承相同的属性值:
var Building=function(){...}
Building.prototype.sight=350;
TerranBuilding.CommandCenter=...(CommandCenter extends Building)
TerranBuilding.Barracks=...(Barracks extends Building)
所以指挥中心和兵营都将有与350相同的建筑视线。
new CommandCenter().sight===new Barracks().sight//All buildings have same sight
1.缓冲效果覆盖原始属性并删除缓冲
Marine.prototype.speed=20
var unit=new Marine()
unit.speed===20//get unit.__proto__.speed 20
unit.speed=5//Buffer:slow down speed, unit.speed will override unit.__proto__.speed
delete unit.speed//Remove buffer
unit.speed===20//true, speed restore
所以我认为应该增加一个设置prototype属性的方法而不是完全禁止它,或者你能给予一些其他的解决方案来处理以上两种情况吗?
6条答案
按热度按时间ktca8awb1#
这两个都不会出现在类别原型上。
class Foo { bar = 1; }
语法会将值指派给类别执行严修,以this.bar
存取。class Foo { static bar = 1; }
语法会将值指派给类别建构函式,以Foo.bar
存取。在这种情况下,没有太多理由使用原型,它只会使谁真正拥有属性变得复杂,并且在几个不同的类中分配一个数字的开销非常小。
我建议使用类示例属性,并在任何需要的地方使用
this.sight
。dtcbnfnu2#
更新答案(2022年4月)
就在我上次答复的两个月后,也就是2021年8月,TC-39委员会将静态块提案移至第4阶段。参见完整的已完成提案非正式列表here。
对于那些希望获得Javascript中静态块的用例摘要的人,请阅读V8博客中2021年3月发布的初始出版物,在它们实现之后。
另请参阅MDN文件以取得静态初始化区块。
虽然大多数更新的浏览器现在都支持此功能,但如果您真的想支持Internet Explorer,请阅读下面的内容。
原始答案
下面是我在javascript中遵循的典型模式。
它反映了java使用的静态块风格。现在有一个Stage 3 Proposal为此开放,我希望它在不久的将来会被标准化(这与TC-39委员会第三阶段的提案期望一致)。
提案的外观
这可以在今天使用静态生命来完成
它们的功能完全相同。
yvt65v4c3#
将属性添加到类体 * 内的原型 * 的最简单方法是使用原型赋值作为伪静态属性的“值”:
(it不使用括号,因为
=
是右关联的,可以对每个原型赋值重复使用相同的伪属性)如果你想对值进行更有趣的(多行)计算,初始化器可以是一个立即执行的函数表达式,在这种情况下,你基本上已经创建了一个static constructor,你可以把原型和类对象的所有初始化都放在其中。
g0czyy6m4#
我认为另一个答案没有理解这个问题的要点。拥有继承的全部要点是你可以决定何时何地重写某些东西。如果有人认为这是一个开销,你为什么要使用OOP语言呢?
我不知道为什么它是“禁止的”,但我可以分享一些想法。我很确定没有办法用'class'关键字定义一个 Prototype 属性。任何定义都将安装在“hasOwnProperty”上。一个巨大的挫折是在构造函数中,没有办法让任何父代的构造函数与一个被覆盖的属性交互。
就推理而言,它实际上是被另一个特性所驱逐的:您可以使用表达式将属性分配给***this***。
当一个表达式出现借口时,它要么运行于 instance(用构造函数创建),要么运行于类声明(当创建 prototype 时)。
访问器和方法没有这个问题。它们在 * 原型定义时 * 定义,在 * 示例运行时 * 调用。
用表达式定义的属性(带有“=”)是表达式的返回值。它在定义后立即被免除-应该是 * 示例创建时间 *,否则 * 此 * 将不可用。
所以这与模式无关,这与表达式或继承有关,我更喜欢继承,表达式是如此的没有意义,当你可以直接把它们写进构造函数中。
使用装饰器是一个很好的解决办法。你可以用javascript中的原型做一些事情:
装饰者B是:
nbewdwxp5#
使用 *Class静态初始化块 *1:
this
与静态块中的1:静态区块内的
this
会指涉类别的建构函式对象。静态区块内的程式码只会在评估类别初始化时执行一次。
注:Safari自2022年6月起不支持此功能。您可以在mdn web docs1上查看最新信息。
[1][https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_static_initialization_blocks](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Class_static_initialization_blocks)
0dxa2lsx6#