我从定义2个独立构造函数开始。
var Sword = function (attack,price){
this.attack = attack;
this.price = price;
};
var LegendarySword = function (){
this.instantKill = true;
};
这些构造函数创建的对象显然彼此无关。
var sword = new Sword(1, 100);
console.log(sword);
//Object
attack: 1
price: 100
__proto__: Object
var superSword = new LegendarySword();
console.log(superSword);
//Object
instantKill: true
__proto__: Object
我现在希望“class”LegendarySword的所有实例都具有Sword“class”特征的属性,即攻击和价格值。这是因为所有传说中的剑最后都是剑,但具有一些独特的属性(如“instantKill”)。
因此,在阅读了原型和继承之后,我发现我可以笑着这样做:
LegendarySword.prototype = new Sword();
我理解这一行的方式是,除了我在构建LegendarySword类的新对象时LegendarySword已经拥有的内容之外,我还在使用Sword的构造函数。我希望LegendarySword对象获得攻击和价格属性,但同时我不希望Sword对象获得instantKill属性。
我还希望我现在可以在LegendarySword构造函数中提供参数:
var superSword2 = new LegendarySword (5, 1000);
我希望这会接受参数,就像Sword构造函数那样,但它显然不会:
console.log(superSword2.attack); // results to undefined (which proves that it has them dug in somewhere in the __proto__, which is so indeed)
看起来我仍然可以解决从另一端接近它的问题。如果我有点,我认为,在创建新的Legendary Sword对象时,不必要地使构造函数复杂化并向Sword添加新方法并调用这些方法并传递参数:
var Sword = function (attack,price){
this.attack = attack;
this.price = price;
this.setAttack = function(attack){
this.attack = attack;
};
this.setPrice = function(price){
this.price = price;
};
};
var LegendarySword = function (attack, price){
this.instantKill = true;
this.setAttack(attack);
this.setPrice(price);
};
LegendarySword.prototype = new Sword();
var sword = new Sword(1, 100);
console.log(sword);// gives correct object attributes
var superSword = new LegendarySword(10,5000);
console.log(superSword); // gives correct object attributes
但这真的很难看,我的问题是为什么当我调整构造函数的原型时Javascript无法确定需要添加新属性?这对我来说非常直观。
是否有其他方法可以解决问题?
答案 0 :(得分:2)
我希望这会接受参数,就像Sword构造函数那样,但它显然不会:
你不应该期望,修改构造函数的原型并不会修改构造函数本身。
> console.log(superSword2.attack);
> // results to undefined
> // (which proves that it has them dug in somewhere in
> // the __proto__, which is so indeed)
它没有证明这一点。您不知道该属性是否存在,因为访问不存在的属性也会返回 undefined (在这种情况下实际发生的情况)。
当你这样做时:
LegendarySword.prototype = new Sword();
您只需将 LegendarySword 的默认原型替换为 Sword 的实例,它不会修改 LegendarySword 本身,因此<构造函数不会添加em> attack 和 price 属性。
如果您希望 LegendarySword 的实例与 Sword 具有相同的属性,则可以执行以下操作:
var LegendarySword = function (attack, price){
// Add Sword properties
Sword.call(this, attack, price);
// Add LegendarySword properties
this.instantKill = true;
};
设置所需的原型链并使用 Sword 属性初始化 LegendarySword 。
答案 1 :(得分:1)
要解决您的问题,您只需要这样做:
var Sword = function (attack,price){
this.attack = attack;
this.price = price;
};
var LegendarySword = function (attack, price){
this.instantKill = true;
Sword.call(this, attack, price)
};
var sword = new Sword(1, 100);
console.log(sword);// gives correct object attributes
var superSword = new LegendarySword(10,5000);
console.log(superSword); // gives correct object attributes
因此,在这种情况下,您甚至不需要使用原型:您只需在子项中调用父函数并传递新函数。
JS中继承的基本解决方案是:
function basicInherit(Child, Parent) {
var F = function () { };
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child;
Child.super = Parent.prototype;
}
有时你可能不想调用父类的构造函数。另外我们不能只做Child.prototype = Parent.prototype,因为如果我们更改子原型,它将反映在父原型中。因此我们将原型从Parent复制到空F类,然后从F继承Child。
如果要继承原型属性,使用此类继承是有意义的,例如:
Sword.prototype.setPrice = function (price) { this.price = price; }
但无论如何 - 在新的子类中调用构造函数 - 这取决于你。
不要在JS中做这些事情:
var Sword = function (attack,price){
this.attack = attack;
this.price = price;
this.setAttack = function(attack){
this.attack = attack;
};
}
因为每次创建新实例时都会创建一个新的setAttack函数实例。
所以,最好把它放在原型
中