2011-12-08 24 views
191

可能重複:
Understanding prototypal inheritance in JavaScript原型的目的是什麼?

OK,所以我有點新的JS在面向對象的思想。

什麼的代碼這兩個片段之間的區別下面寫:

function animal(){ 
    this.name = 'rover'; 
    this.set_name = function(name){ 
     this.name = name; 
    } 
} 
function animal(){ 
    this.name = 'rover'; 
} 
animal.prototype.set_name = function(name){ 
    this.name = name; 
} 

他們都做同樣的事情,所以有什麼區別?

+0

實例級別共享成員(非靜態)的類。例如)Person.prototype.instance_counter = 0; //不能用ClassName像Person.instance_counter(這是靜態的)訪問。 –

回答

271

使用原型可以更快地創建對象,因爲每次創建新對象時都不必重新創建該函數。

當你這樣做:

function animal(){ 
    this.name = 'rover'; 
    this.set_name = function(name){ 
     this.name = name; 
    } 
} 

set_name功能創建從頭每一次您創建一個動物。但是當你這樣做時

animal.prototype.set_name = function(name){ 
    this.name = name; 
} 

函數不必每次都重新創建;它存在於原型中的一個地方。因此,當您撥打someAnimal.set_name("Ubu");時,this上下文將被設置爲someAnimal,並且(唯一的)set_name函數將被調用。


有一個優勢,使用第一種語法,但:以這種方式創建的函數可以訪問私人數據:

function animal(){ 
    var privateData = 'foo' 

    this.name = 'rover'; 
    this.set_name = function(name){ 
     this.name = name; 
     alert(privateData); //will alert 'foo' 
    } 
} 

道格拉斯·克羅克福德稱這樣的「特權」創建功能出於這個原因:他們可以訪問公共和私人數據。

28

的差異,當你從這些函數來創建新的對象

var animal1 = new animal(); 

第一函數創建將有不同的nameset_name性質的所有對象出現。但是,由第二個函數創建的所有對象將共享set_name屬性。

19

在第一個示例中,每個單獨的動物對於set_name函數都有自己的屬性,而在第二個示例中,它們通過它們的原型共享相同的函數。

第一個版本的優點是方法可以訪問在構造函數中聲明的本地(私有)變量。

第二種方法的優點是它只需要較少的內存(因爲您只存儲一次而不是一百萬次),並且在當前的JS引擎中更具性能。

使用第二種方法,您還可以修改方法或將方法添加到類中,同時還會影響已創建的實例。