簡體   English   中英

構造函數原型 - 繼承混淆

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM