我目前面临一个棘手的问题,我无法在javascript中解决。例如,我有一个函数对象Unit
。这是基础对象。
有两个函数对象Tank
和AirDefense
是原型继承自Unit
A"孩子" Unit
有两个属性level
(正常整数)和damagePerSecond
(一个整数数组,其中索引表示该级别上的每秒伤害的级别和值)。
level
应该是"静态"属性,所以每当我更改 AirDefense
或 Tank
的实例级别时,之前创建的每个实例都必须是更新并应用更改的级别
但是也应该有一个静态更改级别的界面,这样我就不必在具体实例上调用setLevel
方法,而是在函数对象本身上调用。
问题在于我正在实现一个名为getDamagePerSecond()
的方法,它返回当前级别的每秒伤害。但是父母不知道具体子对象的当前级别。
我不能在基础对象上使用静态属性,因为它会为对象Tank
和AirDefense
设置级别,但是应该为每个子对象分隔级别。
tl; dr:我想从父对象中使用子对象静态属性,但我还不知道父对象中的子对象。
我将提供迄今为止我尝试过的内容,以便了解这些对象如何协同工作。
单元
function Unit(){
this.level;
this.damagePerSecond;
}
Unit.prototype.getDamagePerSecond = function(){
return this.damagePerSecond[this.level];
};
Unit.prototype.getLevel = function(){
return this.level+1;
}
罐
function Tank(){
this.level = Tank.level || 0;
this.dps = [5,10,15];
}
Tank.prototype = new Unit();
Tank.setLevel = function(level){
Tank.level = level-1;
}
的AirDefense
function AirDefense(){
this.level = AirDefense.level || 0;
this.dps = [1,5,9];
}
AirDefense.prototype = new Unit();
AirDefense.setLevel = function(level){
AirDefense.level = level-1;
}
主要(正确结果)
Tank.setLevel(5);
var t = new Tank();
var a = new AirDefense();
console.log(t.getLevel()); //outputs 5
console.log(a.getLevel()); //outputs 1
主要(错误的结果)
var t = new Tank();
Tank.setLevel(5);
var a = new AirDefense();
console.log(t.getLevel()); //outputs 1 - should be 5
console.log(a.getLevel()); //outputs 1
我基本上做的是伪造具体对象中的静态属性。 Level是我的子对象的静态属性。在实例化期间,我有一个额外的实例属性,其级别将设置为假静态属性的值。
但是这里出现了一些问题:
我只能在实例化之前为对象类型设置一个级别。但我想改变两者的水平,所有已经实例化的对象以及未来的对象。
使用这种方法,我需要在所有子对象上实现setLevel()
方法。我认为这与干相反。
通过提供静态接口,无法直接发送已存在的具体实例
如果我在谈论原型时使用了不常见的术语,我很抱歉。我来自具有经典OO方法的语言。
我还不熟悉原型继承,所以我希望有人能给我一个正确的方向。
答案 0 :(得分:1)
所有Tank实例应该共享级别吗?你可以这样做:
function Unit(){}
Unit.prototype.getLevel = function(){
return this.level+1;
};
function Tank(){
//level should be shared by all Tanks
// setting this.level shadows Tank.prototype.level
// so let's not do that
// this.level = Tank.level || 0;
}
//not sure why you want a Unit instance to be
// prototype of all Tanks
Tank.prototype = Object.create(Unit.prototype);
Tank.prototype.constructor=Tank;
Tank.prototype.level=5;
Tank.prototype.setLevel = function(level){
//set Tank.prototype.level so it's shared
// for all tank instances
Tank.prototype.level = level-1;
}
//same for AirDefense
var t1 = new Tank();
var t2 = new Tank();
console.log("t1 level:",t1.level,"t2 level",t2.level);
console.log("t1 getLevel:",t1.getLevel(),"t2 getLevel",t2.getLevel());
t1.setLevel(11);
console.log("t1 level:",t1.level,"t2 level",t2.level);
console.log("t1 getLevel:",t1.getLevel(),"t2 getLevel",t2.getLevel());
或者在Tank.prototype上有一个对象成员并改变它。
function Unit(){}
Unit.prototype.getLevel = function(){
return this.shared.level+1;
};
Unit.prototype.setLevel = function(level){
this.shared.level=level;
};
function Tank(){}
Tank.prototype = Object.create(Unit.prototype);
Tank.prototype.constructor=Tank;
Tank.prototype.shared={};
Tank.prototype.shared.level=5;
var t1 = new Tank();
var t2 = new Tank();
console.log("t1 level:",t1.shared.level,"t2 level",t2.shared.level);
console.log("t1 getLevel:",t1.getLevel(),"t2 getLevel",t2.getLevel());
t1.setLevel(11);
console.log("t1 level:",t1.shared.level,"t2 level",t2.shared.level);
console.log("t1 getLevel:",t1.getLevel(),"t2 getLevel",t2.getLevel());
有关构造函数和原型的更多信息,请访问:https://stackoverflow.com/a/16063711/1641941
<强>更新强>
演示继承实例特定和共享(原型)成员。函数通常在原型上,因为它对所有实例都是一样的。构造函数还可以初始化特定于实例的成员(例如damagePerSecond)。无需在Tank和AirDefense中初始化它,因为Unit可以处理它:
function Unit(args){
this.damagePerSecond=args.damagePerSecond;
//..bunch of other instance specific members
}
function Tank(){
//Tank is a Unit so we can take all instance specific Unit members
//inherit instance specific members from Unit
Unit.call(this, {damagePerSecond:[2,3,4]});
}
//inherit shared members from Unit
//... Tank.prototype = Object.create(Unit.pro ... bla bla bla
var t = new Tank();
console.log(t.damagePerSecond);//=[2,3,4]
args是一个可以传递给构造函数的对象,我可以将它传递给Tank,Tank可以通过以下方式传递给Unit:
function Tank(args){
args=args||{};//don't worry if no args are passed
args.damagePerSecond=args.damagePerSecond||[2,3,4];//passed arg or default
//... and a bunch of other stuff
Unit.call(this,args);
}
var t = new Tank();//all defaults
var t1 = new Tank({damagePerSecond:[7,8,9]});//super Tank
当您有调用其他函数的函数时,使用这样的模式非常有用。当你定义像someFunction(who, what, when)
这样的严格,并且你将拥有一长串函数时,如果需要在开头添加一个名为where
的额外变量,那么你需要进行大量的输入。仅在最后使用。
我之前发布的链接涵盖了大部分内容。