我正在尝试ES6语法并发现我无法在类定义中定义原型属性或实例属性,为什么禁止它?
之前我使用的是MyClass.prototype.prop=1
,如下所示通过babel编译器尝试ES7,仍然无法定义原型属性。
class MyClass{
prop=1;
static sProp=1;
}
我不认为define instance属性是危险的,我自己的浏览器游戏中有2例需要原型属性:
子类实例需要从基类继承相同的属性值:
var Building=function(){...}
Building.prototype.sight=350;
TerranBuilding.CommandCenter=...(CommandCenter extends Building)
TerranBuilding.Barracks=...(Barracks extends Building)
因此,CommandCenter和军营将拥有与350相同的建筑物视野。
new CommandCenter().sight===new Barracks().sight//All buildings have same sight
缓冲区效果覆盖原始属性并删除缓冲区
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
所以我认为它应该添加一种方法来设置原型属性而不是完全禁止它,或者你能否提供一些其他解决方案来处理上述两种情况?
答案 0 :(得分:4)
这些都不会出现在班级原型上。
this.bar
语法会为http://jsfiddle.net/drx389j5/分配一个值,以class Foo { static bar = 1; }
方式访问。
Foo.bar
语法会为class instance分配一个值,以this.sight
方式访问。
在这种情况下使用原型没有多大理由。它只会使实际拥有该属性的人变得复杂,并且在几个不同的类中分配一个数字将具有非常小的开销。
我建议使用类实例属性,只需在需要的地方使用{{1}}。
答案 1 :(得分:1)
将属性添加到类主体内的原型 的最简单方法是将原型分配用作虚拟静态属性的“值”:
class MyClass {
static _dummy = MyClass.prototype.prop1 = <expression1>
static _dummy = MyClass.prototype.prop2 = <expression2>
// or
static _dummy = this.prototype.prop2 = <expression2>
}
(它没有括号就可以工作,因为=
是右关联的,并且可以为每个原型分配重新使用相同的虚拟属性)
如果您想对值进行更多有趣的(多行)计算,则初始化程序可以是立即执行的函数表达式,在这种情况下,您基本上已经创建了static constructor并可以将所有原型和类对象的初始化。
答案 2 :(得分:0)
我认为另一个答案没有说明这个问题。继承的全部意义在于您可以决定何时何地覆盖。如果有人认为这是一个开销,为什么你会使用OOP语言?
我不知道为什么它会被“禁止”,但我可以分享一些想法。 我很确定没有办法用'class'关键字定义 Prototype 属性。任何定义都将安装在“hasOwnProperty”上。一个巨大的挫折是,在构造函数中,没有办法让任何父项的构造函数与重写的属性进行交互。
在推理方面,它实际上已被其他功能驱逐:您可以使用表达式将属性分配给 此 。
class A extends B { sight = this.getSight() * 3 }
当表达式找借时,它可以使用 instance 运行 - 使用构造函数创建,或者在类声明中运行 - 创建 prototype 时。
访问者和方法没有这个问题。它们在原型定义时间中定义,并在实例运行时处调用。
使用带有“=”的表达式定义的属性是表达式的返回值。在定义之后立即解释 - 应该是实例创建时间,否则此无法使用。
所以这与模式无关。这是关于表达或继承。我绝对更喜欢继承,当你可以将它们写入构造函数时,表达式是如此毫无意义。
class A extends B { constructor() { this.sight = this.getSight() * 3 }
使用装饰器是一个很好的解决方法。您可以随时使用javascript中的原型执行某些操作:
@B({sight:2}) class A {};
装饰者B是:
function(option) {return function(clazz) {clazz.prototype.sight = option.sight; return clazz}}
答案 3 :(得分:0)
以下是我在 JavaScript 中遵循的典型模式。原生的,没有 babel 等等。
它反映了java使用的静态块风格。目前有一个 Stage 3 Proposal 对此开放,我希望它会在不久的将来标准化(与 TC-39 委员会对第 3 阶段提案的期望一致)。
class MyClass {
static {
// Any code here is executed directly after the initialization
// of MyClass. You can add prototype stuff here. The function
// is called bound to `MyClass`.
}
}
它们的功能完全相同。
class MyClass {
// Using private properties is not required, it is just an option. Make
// sure to use an arrow function so that `this` refers to `MyClass`,
// Note that `MyClass` will still be in the functions closure.
static #_ = (() => {
// 'Almost' how functions are typically added. ES6 style
// is always recommended over this.
this.prototype.myFunc = function myFunc() {
console.log(":D");
};
// ES6 would actually do this (approximately) so that the function is
// non-enumerable in the prototype.
Reflect.defineProperty(this.prototype, "myFunc", {
// enumerable: false, // defaults 'false'
writable: true,
configurable: true,
// I'm intentionally not using the shorthand for the function
// so that it is named 'myFunc'.
value: function myFunc() {
console.log(":D");
}
});
// Note that all children of MyClass will refer to this exact
// object if put in the prototype, i.e. not a copy of it.
// Also, this property will be non-enumerable on the children
// (but enumerable on the prototype itself unless you
// use `defineProperty` as above).
this.prototype.sharedProperty = { name: "Gerald" };
})();
}
答案 4 :(得分:-1)
class MyClass {
constructor() {
MyClass.prototype.prop2 = "Marry";
}
}
const mc = new MyClass()
mc.__proto__ // { prop2: "Marry" }