我有这堂课
driver.execute_script("window.open('%s');" % url)
//一些接口(方法)
class MyClass {
constructor(name, health, damage){
INamable(this)
IHealth(this)
IDamage(this)
IAttack(this)
ITakeDamage(this)
this.setName(name)
this.setHealth(health)
this.setDamage(damage)
}
attack(target){
target.takeDamage(this.getDamage());
}
takeDamage(damage){
this.setHealth(this.getHealth() - damage);
if(this.getHealth()<=0){
this.die();
}
}
toString(){
return "myClassToString"
}
}
我的问题是,为什么 function IAttack(object){
let attack = function(){}
object.attack = attack;
}
function ITakeDamage(object){
let takeDamage = function(){}
object.takeDamage = takeDamage;
}
和attack(target)
不覆盖构造函数中继承的方法。我知道这可能是以前问过的,但我找不到抱歉。
答案 0 :(得分:4)
在注释中,@ Bergi假设您可能正在运行时实例化新的MyClass对象并引用它们。因为您尝试更改MyClass对象实例的方法而不是其原型,所以MyClass的所有新实例(使用“ new”关键字创建)仍将继承原始MyClass的属性。
例如,考虑一个水果类
class Fruit {
constructor() {
this.pieces = 1;
}
cutIntoPieces(pieces) {
this.pieces = pieces;
return this;
}
}
和一个函数f
,该函数接受任何对象并更改其属性cutIntoPieces
,并将其设置为一个无条件返回null且不执行其他任何操作的函数:
const f = object => {
object.cutIntoPieces = () => null;
};
让我们在Node REPL中尝试一下:
> banana = new Fruit();
Fruit { pieces: 1 }
> orange = new Fruit();
Fruit { pieces: 1 }
> papaya = new Fruit();
Fruit { pieces: 1 }
> f(banana);
undefined
> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }
> orange.cutIntoPieces(3);
Fruit { pieces: 3 }
> papaya.cutIntoPieces(4);
Fruit { pieces: 4 }
您可以看到,在将香蕉切成小块时,在香蕉上调用f
会改变其行为。之所以发生这种情况,是因为现在香蕉具有自己的属性 cutIntoPieces
,该函数无条件返回null并且不影响对象。
要在对象的所有实例中重新定义方法cutIntoPieces
,我们需要在其原型(即Fruit)中对其进行更改:
> Object.getPrototypeOf(banana);
Fruit {}
要创建一个采用对象原型并更改其属性的函数,以便该对象的所有实例都继承更改后的属性,我们需要稍微重新构建函数f
。让我们声明另一个函数并将其命名为g
:
const g = object => {
object.cutIntoPieces = function (cuts) {
this.pieces = 2 ** cuts;
return this;
};
};
在这里,g
重新定义了任何对象的方法cutIntoPieces
,以提高切割效率。现在,如果我们使用Fruit.prototype调用g
,它将更改orange和木瓜的方法cutIntoPieces
:
> g(Fruit.prototype);
undefined
> orange.cutIntoPieces(4);
Fruit { pieces: 16 }
> papaya.cutIntoPieces(10);
Fruit { pieces: 1024 }
那香蕉怎么了?
> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }
因为我们在香蕉上叫f
,所以banana.cutIntoPieces
现在与Fruit.prototype.cutIntoPieces
无关。尽管Orange和木瓜具有从原型继承的此方法,但香蕉有其自己的:
> orange.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> papaya.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
false
那很好,我猜。如果只想更改一个实例的行为,则可以定义自己的属性,自己的方法;另一方面,当您需要更改所有具有从原型继承的方法的实例的行为时,可以更改其原型。
但是,当将香蕉切成小块时,如何使其表现与其他水果相同?让我们删除它自己的cutIntoPieces
!
> delete banana.cutIntoPieces
true
> banana
Fruit { pieces: 1 }
> banana.cutIntoPieces(2)
Fruit { pieces: 4 }
请参见,在删除对象自己的属性后,如果有一个属性,则将从原型继承另一个同名属性:
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
现在香蕉,橙子和木瓜的行为相同。
希望它能帮助您,并祝您好运!