[英]Constructor prototype - inheritance confusion
我從定義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無法確定是否需要添加新屬性? 這對我來說非常直觀。
是否有其他方法可以解決問題?
我希望這會接受參數,就像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();
您只需使用Sword實例替換LegendarySword的默認原型,它不會修改LegendarySword本身,因此構造函數不會添加攻擊和價格屬性。
如果您希望LegendarySword的實例具有與Sword相同的屬性,您可以執行以下操作:
var LegendarySword = function (attack, price){
// Add Sword properties
Sword.call(this, attack, price);
// Add LegendarySword properties
this.instantKill = true;
};
其中設置了所需的原型鏈並使用Sword屬性初始化LegendarySword 。
要解決您的問題,您只需要:
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函數的新實例。
所以,把它放在原型中會更好
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.