簡體   English   中英

通過.prototype添加到對象的方法不被繼承嗎?

[英]Method added to object via .prototype isn't being inherited?

我是Javascript的新手,這是有關繼承的基本問題。

在我正在查看的網站中,向對象的原型添加新方法看起來非常簡單。 這是他們顯示的方法:

function Gadget(name, color) { 
   this.name = name; 
   this.color = color; 
}

Gadget.prototype.getInfo = function() { 
   return 'Rating: ' + this.rating + ', price: ' + this.price;
};

但是,嘗試復制同一件事,我得到一個錯誤:

(function() {

    window.onload = function() {
        document.getElementById("main").innerHTML = getMessage();
    }

    function Animal(){
        this.speak = function(){
            return "I am a " + this.species + ", hear me " + this.sound + "!";
        }
    }

    function Cat(){
        this.__proto__ = new Animal();
        this.species = "cat";
        this.sound = "meow";
    }

    function getMessage(){
        var cat = new Cat();
        Cat.prototype.pounce = function() { return "Pounce!"};    //Adding prototype function here

        var Boots = {};
        Boots.__proto__ = new Cat();

        return cat.speak() + '<br>' + Boots.pounce();   //Returning message that Boots.pounce() doesn't exist
    }

})()

當我在調試窗口中查看Cat()對象時,它顯示出它沒有屬性“ pounce”,而Boots也沒有。 我在這里做什么是行不通的?

我認為,由於我已將函數添加到對象的原型中,因此它將被添加到原型鏈中並因此被繼承。

非常感謝您的寶貴時間。

__proto__的行為從未標准化過,除了作為傳統功能

如果使用Object.create方法,將會有更好的時間。 它以原型為第一個參數,並返回使用該原型的對象。

您的代碼(如果用Object.create重寫)可能更像這樣。

function Animal() {

}

// you don't need to this, but it shows the prototype chain explicitly
Animal.prototype = Object.create(Object.prototype);

Animal.prototype.speak = function() {
  return "I am a " + this.species + ", hear me " + this.sound + "!";
};

function Cat(){
  this.species = 'cat';
  this.sound = 'meow';
}

Cat.prototype = Object.create(Animal.prototype);

Cat.prototype.pounce = function() {
  return "Pounce";
};

function getMessage() {
  var cat = new Cat();

  // you could dynamically add methods to the prototype, but the
  // code will be faster if you declare the properties on the
  // prototype, as early as possible

  var Boots = new Cat();
  return cat.speak() + '<br>' + Boots.pounce();
}

那不是您使用原型的方式,所以讓我們以一種更加標准化的方式重建它:

function Animal(){
    this.species = 'Undefined';
    this.sound = 'silence';
}

Animal.prototype = {
    speak: function(){
        return "I am a " + this.species + ", hear me " + this.sound + "!";
    }
}

function Cat(){
    Animal.apply(this);
    this.species = 'cat';
    this.sound = 'miauw';
}

Cat.prototype = Object.create(Animal.prototype);
Cat.prototype.pounce = function(){ return 'Pounce!'; }

那么我們在這里做了什么? 我們從創建一個function ,這通常稱為構造函數 它主要用於設置存儲的參數。 然后,我們創建一個原型object ,它包含了你的方法(和潛在的原型參數) prototype

要創建Cat,我們創建另一個函數,並首先將第一個function與當前的this對象一起應用。 這使您可以繼承原始構造函數在運行時所做的一切。 它實際上是在Animal上運行安裝程序,但在我們的新Cat上運行。 然后,您可以進行自定義操作,例如將種類設置為“貓”。 之后,我們將復制 Animal的現有原型,然后向其添加更多方法。

需要注意的是,所有這些都進入了prototype密鑰,而不是 __proto__ 以雙下划線開頭的鍵和變量是您切勿觸摸且幾乎絕不使用自己的東西-它們被視為系統為您執行的操作。 您之前看到的__proto__是通過編程應用prototype的結果,您可以在控制台中看到它,但這不是您應該弄混的東西。

現在我們可以做這樣的事情:

 // Ignore this bit, it's a repeat of the code above // so I condensed it to a single line. Otherwise, exactly the same. function Animal(){ this.species = 'Undefined'; this.sound = 'silence';}Animal.prototype = {speak: function(){return "I am a " + this.species + ", hear me " + this.sound + "!";}}; function Cat(){Animal.apply(this);this.species = 'cat';this.sound = 'miauw';}Cat.prototype = Object.create(Animal.prototype);Cat.prototype.pounce = function(){ return 'Pounce!'; } // Helper function so the code reads clearly, // but also writes to the snippet and adds the linebreaks // and strong tags where necessary function w(m,s){document.write((s?'<strong>':'')+(m?m:'')+(s?'</strong>':'')+'<br />');}; // Create our variables with the animal and the cat var justAnAnimal = new Animal(); var pussInBoots = new Cat(); w( 'Speaking', true ); w(); w( 'justAnAnimal.speak()', true ); w( justAnAnimal.speak() ); w( 'pussInBoots.speak()', true ); w( pussInBoots.speak() ); w(); w('Pouncing', true); w(); w( 'justAnAnimal.pounce()', true ); // Use variable.method to check if the method exist // if it does, then execute it and write that with variable.method() // Otherwise print a different message so we know whats going on. w( (justAnAnimal.pounce && justAnAnimal.pounce()) || 'Not every animal pounces (method does not exist for this instance)!' ); w( 'pussInBoots.pounce()', true ); w( (pussInBoots.pounce && pussInBoots.pounce()) || 'Not every animal pounces (method does not exist for this instance)!' ); w(); w('Checking the type of your animals using instanceof', true); w(); w( 'is justAnAnimal an Animal?', true ); w( justAnAnimal instanceof Animal ? 'Yes' : 'No' ); w( 'is justAnAnimal a Cat?', true ); w( justAnAnimal instanceof Cat ? 'Yes' : 'No' ); w( 'is pussInBoots an Animal?', true ); w( pussInBoots instanceof Animal ? 'Yes' : 'No' ); w( 'is pussInBoots a Cat?', true ); w( pussInBoots instanceof Cat ? 'Yes' : 'No' ); 
 body { font-family: 'Monaco', 'Courier MS', courier, monospace; font-size: 10px; } strong { color: #777; margin-right: 20px; display: inline-block; font-weight: normal; } 

我發現這使您的代碼看起來更加簡潔,因為一切都非常簡單。 構造函數,原型,所有內容都落入易於區分且易於閱讀的模式。

以下是MDN上的綜合文章: https : //developer.mozilla.org/en/docs/Web/JavaScript/Inheritance_and_the_prototype_chain

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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