构造函数原型-继承混淆
Constructor prototype - inheritance confusion
我首先定义两个独立的构造函数。
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
我现在希望"类"传奇之剑的所有实例都具有剑"类"的特性,即攻击和价格值。这是因为所有传说中的剑最终都是剑,但具有一些独特的特性(如"instantKill"(。
所以,在阅读了原型和继承之后,我发现我可以笑着这样做:
LegendarySword.prototype = new Sword();
我理解这句话的方式是,当我构建传奇之剑类的新对象时,除了传奇之剑已经拥有的构造函数之外,我还使用了剑的构造函数。我希望传说之剑的物体获得攻击和价格属性,但同时我不希望剑的物体得到instantKill属性。
我还希望我现在能够在传奇之剑构造函数中提供论据:
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)
看起来我仍然可以从另一端解决问题。如果我有点像我认为的那样,不必要地使构造函数复杂化,并向Sword添加新方法,并在创建新的Legendary 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不能弄清楚需要添加新的属性?这对我来说太直观了。
有没有其他方法可以解决这个问题?
我希望这能像Sword构造函数一样接受争论,但显然不是:
你不应该期望,修改构造函数的原型并不会修改构造函数本身。
> console.log(superSword2.attack);
> // results to undefined
> // (which proves that it has them dug in somewhere in
> // the __proto__, which is so indeed)
这并不能证明这一点。您不知道该属性是否存在,因为访问不存在的属性也会返回未定义(这就是本例中实际发生的情况(。
当你这样做:
LegendarySword.prototype = new Sword();
您只需将传奇之剑的默认原型替换为剑说之剑本身,因此构造函数不会添加攻击和价格属性。
如果您希望传奇之剑的实例具有与剑s相同的属性,您可以执行以下操作:
var LegendarySword = function (attack, price){
// Add Sword properties
Sword.call(this, attack, price);
// Add LegendarySword properties
this.instantKill = true;
};
它设置了所需的原型链,并使用剑属性初始化传奇剑
仅解决方案
要解决你的问题,你只需要做:
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
所以在这种情况下,你甚至不需要使用原型:你只需要在子函数中调用父函数并传递新的this。
原型继承
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函数的新实例。
因此,最好将其放在原型中
- JavaScript对象不是从原型链继承的
- 如何使用原型继承编写一个整洁灵活的复杂javascript应用程序
- $emit,$broadcast,原型继承
- Javascript:继承原型而不重新定义构造函数
- 原型继承未按预期工作
- JavaScript中的原型继承.我可以称之为“超级”等价物吗?
- 为什么函数对象的实例没有继承函数原型属性
- 不创建父对象的原型继承
- Javascript基本继承与Crockford原型继承
- JavaScript-构造函数参数和原型继承
- 使用Object.create作为原型的原型继承将[Object]作为实例的原型
- javascript继承中正确的原型做作是什么
- 如何进行JavaScript原型继承(原型链)
- Javascript原型继承原型函数调用
- 对象不继承原型函数
- 从其他类继承原型方法,而不重写自己的原型方法
- JavaScript继承原型
- 继承原型
- Javascript继承/原型混淆
- 使用.call(this)继承原型