Al *_*ram 2 javascript ecmascript-6
我有这门课
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"
}
}
Run Code Online (Sandbox Code Playgroud)
// 一些接口(方法)
function IAttack(object){
let attack = function(){}
object.attack = attack;
}
function ITakeDamage(object){
let takeDamage = function(){}
object.takeDamage = takeDamage;
}
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么attack(target)不takeDamage(damage)重写构造函数中继承的方法。我知道以前可能有人问过这个问题,但抱歉我找不到。
在评论中,@Bergi 假设您可能在运行时实例化新的 MyClass 对象并引用它们。因为您尝试更改 MyClass 对象实例的方法,而不是其原型,所以所有新的 MyClass 实例(使用“new”关键字创建)仍将继承原始 MyClass 的属性。
例如,考虑一类 Fruit
class Fruit {
constructor() {
this.pieces = 1;
}
cutIntoPieces(pieces) {
this.pieces = pieces;
return this;
}
}
Run Code Online (Sandbox Code Playgroud)
f以及一个接受任何对象并更改其 property 的函数cutIntoPieces,将其设置为无条件返回 null 且不执行任何其他操作的函数:
const f = object => {
object.cutIntoPieces = () => null;
};
Run Code Online (Sandbox Code Playgroud)
让我们在 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 }
Run Code Online (Sandbox Code Playgroud)
您可以看到,f当您想将香蕉切成碎片时,调用香蕉会改变它的行为。发生这种情况是因为现在bananas有了自己的property cutIntoPieces,它是一个无条件返回null并且不影响对象的函数。
要在对象的所有cutIntoPieces实例中重新定义方法,我们需要在它们的原型(即 Fruit)中更改它:
> Object.getPrototypeOf(banana);
Fruit {}
Run Code Online (Sandbox Code Playgroud)
为了创建一个接受对象原型并更改其属性的函数,以便该对象的所有实例都继承更改后的属性,我们需要f稍微重新创建我们的函数。让我们声明另一个函数并调用它g:
const g = object => {
object.cutIntoPieces = function (cuts) {
this.pieces = 2 ** cuts;
return this;
};
};
Run Code Online (Sandbox Code Playgroud)
这里,g重新定义了任意对象的方法cutIntoPieces,让切割更加高效。现在,如果我们用Fruit.prototype调用,它将改变orange和papaya的g方法:cutIntoPieces
> g(Fruit.prototype);
undefined
> orange.cutIntoPieces(4);
Fruit { pieces: 16 }
> papaya.cutIntoPieces(10);
Fruit { pieces: 1024 }
Run Code Online (Sandbox Code Playgroud)
那香蕉怎么了?
> banana.cutIntoPieces(2);
null
> banana
Fruit { pieces: 1, cutIntoPieces: [Function] }
Run Code Online (Sandbox Code Playgroud)
因为我们叫f香蕉,banana.cutIntoPieces现在已经不相关了Fruit.prototype.cutIntoPieces。虽然橙子和木瓜有从原型继承的这个方法,但香蕉有自己的:
> orange.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> papaya.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
false
Run Code Online (Sandbox Code Playgroud)
我想这很好。如果您只想更改一个实例的行为,您可以定义它自己的属性、它自己的方法;另一方面,当您需要更改所有具有从原型继承的方法的实例的行为时,您可以更改它们的原型。
但如何让香蕉在切成块后表现得与其他水果相同呢?让我们删除它自己的cutIntoPieces!
> delete banana.cutIntoPieces
true
> banana
Fruit { pieces: 1 }
> banana.cutIntoPieces(2)
Fruit { pieces: 4 }
Run Code Online (Sandbox Code Playgroud)
看,当你删除对象自己的属性后,另一个同名的属性将从原型继承,当有一个时:
> banana.cutIntoPieces === Fruit.prototype.cutIntoPieces
true
Run Code Online (Sandbox Code Playgroud)
现在香蕉、橙子和木瓜的行为是相同的。
希望它有帮助,祝你好运!
| 归档时间: |
|
| 查看次数: |
142 次 |
| 最近记录: |