2011-01-30 46 views
30

我意識到這已經被提出了數百次,但是我似乎無法理解JavaScript中「爲什麼」原型的概念是正確的,因爲模仿類(是的,我知道JavaScript是一種基於原型的語言 - 我收集了很多)。像許多其他人一樣,我努力使JavaScript成爲我使用的日常語言,我習慣於使用常規的OOP類風格,正如我在Java中玩過的(並且在ActionScript和PHP中使用類)。然而,雖然我認爲我明白原型的工作原理,但似乎無法理解爲什麼需要它們。試圖理解JavaScript中原型的意義

這裏有一個如何我目前在JavaScript中瞭解我的原型示例腳本:

var Apple = function() { 
    // An apple? 
}; 

Apple.prototype.color = "red"; 

Apple.prototype.changeColor = function(new_color) { 
    this.color = new_color; 
}; 
Apple.prototype.getColor = function() { 
    alert('color: '+this.color); 
}; 

var apple1 = new Apple(); 
var apple2 = new Apple(); 
apple2.changeColor("green"); 
apple1.getColor(); 
apple2.getColor(); 

...我曾以爲也許原型意味着它共享相同的對象,而不僅僅是創建一個新對象每次 - 然而,顯然情況並非如此,因爲apple1和apple2都有不同的顏色,仍然(在運行所述腳本之後)。

然後我寫它更重要的是一個面向對象的腳本:

var Apple = function() { 
    this.color = "red"; 

    this.changeColor = function(new_color) { 
     this.color = new_color; 
    }; 
    this.getColor = function() { 
     alert('color: '+this.color); 
    }; 
}; 

var apple1 = new Apple(); 
var apple2 = new Apple(); 
apple2.changeColor("green"); 
apple1.getColor(); 
apple2.getColor(); 

完全相同的結果(如預期)。 ...爲什麼後面的代碼不被推薦?我沒有問題使用原型(假設我正確使用它們),但我需要了解「爲什麼」的概念。

...有什麼幫助嗎?

回答

31

...我曾以爲也許原型意味着它共享相同的對象,而不是每次只需創建一個新的對象......

它。有一個原型對象在構造函數創建的所有實例中共享。

...但是,顯然並非如此,因爲apple1和apple2都有不同的顏色,仍然(在運行所述腳本之後)。

對於某些類型(例如數字,布爾值,null,未定義或字符串),當您更改通過this.color例如原型對象上存在的屬性,它會創建的實例color屬性。原型不受影響,因此新實例將具有在原型中定義的默認顏色。

如果您已更新由原型對象的屬性引用的數組或對象的成員,則會在所有實例中看到更改。

...爲什麼後面的代碼不被推薦?

因爲您正在構建新的相同函數,並且創建每個新實例,而不是通過原型對象共享一個函數實例。


要展開多一點,我想指出的是,當你的功能是通過使用new關鍵字,this在構造稱爲構造爲新的實例。因此,您添加到this的任何屬性都將添加到實例中。

var Apple = function() { 
     // Here "this" is the object being constructed. As such, we're adding 
     // a property "rotten" to every instance created 
    this.rotten = false; 
}; 

    // adding a "color" property to the prototype object 
Apple.prototype.color = "red"; 

    // set the property "color" on the instance to the value of "new_color" 
Apple.prototype.changeColor = function(new_color) { 
    this.color = new_color; 
}; 
    // first check to see if this instance has its own "color" property. If so, 
    // use it. If not, look at the prototype object to see if it exists. 
Apple.prototype.getColor = function() { 
    alert('color: '+this.color); 
}; 

// two new instances each have their own "rotten" property, and don't have a 
// "color" property. Both share the prototype object, so if "color" is 
// requested, it will come from there 
var apple1 = new Apple(); 
var apple2 = new Apple(); 

// This will add an "color" property to the "apple2" instance 
apple2.changeColor("green"); 

// Doesn't have a "color" property, so it looks to the prototype object 
apple1.getColor(); 

// Has a "color" property, so it uses that instead of the "color" on the prototype 
apple2.getColor(); 
+1

這實際上非常有幫助;謝謝。在引用`Apple.prototype.color`後,我可以看到它仍然是「紅色」,這再次確認了我最初關於引用單個對象的原型的想法。這仍然有點令人困惑,因爲我想直接指定我的方法......功能,但是我想我可能已經掌握了它的方法。再次感謝。 – clicheName 2011-01-30 05:13:15

5

原型允許您將方法和屬性添加到類中,它不僅將其應用於類,而且還將該類應用於該類的任何當前對象實例。

+0

簡單的解釋說清楚。 – 2017-06-12 00:24:51