2010-05-21 113 views
4

我最近纔剛剛開始編程,並且完全自學成才,不幸的是我沒有詳細的計算機科學課程的好處。最近我一直在閱讀關於JavaScript的許多內容,並且我試圖從JavaScript的原型本質中找到類中的好處。這個問題似乎是在一個更好的中間被拉下來的,我想看看它的經典方面。古典結構與原型結構相比有什麼好處?

當我看到原型例如:

var inst_a = { 
    "X": 123, 
    "Y": 321, 
    add: function() { 
    return this.X+this.Y; 
    } 
}; 
document.write(inst_a.add()); 

再經典的版本

function A(x,y){ 
    this.X = x; 
    this.Y = y; 
    this.add = function(){ 
    return this.X+this.Y; 
    }; 
}; 
var inst_a = new A(123,321); 
document.write(inst_a.add()); 

我開始考慮這一點,因爲我期待在新的ECMAScript第5版和大量的人似乎有些擔心他們沒有添加一個班級系統。

+2

好問題;我在這裏問了一個類似的問題:http://stackoverflow.com/questions/2800964/what-are-the-benefits-of-prototypal-inheritance-over-classical – Pierreten 2010-05-21 15:31:57

+0

我會通讀一下,開始。我沒有在我的搜索中找到它。謝謝! – Rixius 2010-05-21 15:32:54

回答

3

如果不使用psuedoclassical樣式,繼承是不可能的。看看道格拉斯克羅克福德對它有什麼say。即使你使用的是純粹的原型對象結構,你也必須爲繼承創建一個構造函數(這是Crockford所做的,然後將其抽象爲create方法,然後將其稱爲純原型)

+0

感謝您的鏈接。 – Rixius 2010-05-21 16:03:44

+0

+1爲繼承 - 優秀的一點和我最喜歡的OOP部分之一。 – Josh 2010-05-21 16:10:04

2

使用第二種方法,您可以創建A的實例,允許您一次有多個實例。例如:

var inst_one = new A(123,321); 
var inst_two = new A(456,654); 

// some meaningful code here... 
document.write(inst_one.add()); 


// some more meaningful code here... 
document.write(inst_two.add()); 

您提供的例子是微不足道的,因此,讓一個更直觀的例子:

function Comment(user,text){ 
    this.user = user; 
    this.text = text; 
    this.toString = function(){ 
    return '<span class="comment">'+this.text+' - <a class="user">'+this.user+'</a></span>'; 
    }; 
}; 


var comments = someFunctionThatReturnsALotOfCommentObjects(); 
for(c=0;c<comments.length;c++) 
    document.getElementById('comments_container').innerHTML += comments[c].toString(); 

這(希望)演示了能夠創建一個類的多個實例的好處。這不是一個基本的JavaScript概念,它是一個基本的概念,如果你沒有正式的編程課程,這可能是你爲什麼不熟悉它的原因。

+0

您還可以使用inst_a的原型創建另一個inst_ *並更新X和Y或添加更多屬性。我個人會實現一個Object.clone,負責複製。 – Rixius 2010-05-21 15:39:09

+0

@Rixius哦,是的。我可以花一整天時間創建OOP如何有用的示例:-D – Josh 2010-05-21 15:40:31

+0

感謝您提供更好的示例。 – Rixius 2010-05-21 15:43:28

3

當您通過new創建對象時,它將使用它的原型鏈來查找實例中未找到的屬性。

因此,例如,您可以將add方法添加到A.prototype一次,而不是每次創建A的新實例時重新定義相同函數的新副本。

function A(x,y){ 
    this.X = x; 
    this.Y = y; 

}; 
//define add once, instead of every time we create a new 'A' 
A.prototype.add = function(){ 
    return this.X+this.Y; 
    }; 
+0

+1,這是更好的風格 – Josh 2010-05-21 15:39:31

0

古典版本允許你聲明私有變量的範圍在對象「內部」,而原型版本不允許。

+0

不正確。您可以在原型版本中創建閉包。 – Josh 2010-05-21 15:41:04

1

爲了公平起見JavaScript 確實有課。那麼,也許有人會爭論,但我認爲它只是頭髮的語義分裂。如果一個類被認爲是用於創建對象的藍圖,那麼JavaScript函數可以以這種身份提供服務。這裏沒有在功能上多區別就在這裏,唯一的形式:

class someObj 
{ 
    private int x; 
    public int returnX() 
    { 
     return x; 
    } 
} 
someObj temp = new someObj(); 

-

function someObj { 
    var x; 
    this.returnX = function() { 
     return x; 
    }; 
} 
var temp = new someObj(); 

下,它們是不同的引擎蓋,但你可以使用任何一種形式來服務同一端。

原型在繼承上真的不同。在原型繼承中,當你創建一個新對象時,你真的在​​複製原型對象的一個​​實例,然後向它添加新的字段或成員。另一方面,古典遺產並不是處理一個實例,而只是一個「藍圖」。例如,在JavaScript中你會說:

temp.prototype = new someOtherObj(); //Creating a new instance to serve as the prototype. 

在經典的語言,你可以說:

class someObj : someOtherObj //Copying the "blue print" over. 

言下之意是,數據將在原型語言派生的對象之間共享。我曾經編寫過一個函數,並通過JavaScript中的原型創建了另一個函數。這個基礎對象持有對DOM對象的引用,並且當我在一個子對象中更改它時,它將更改該子對象的所有實例。這是因爲,原型語言再次來自實例,而不是「藍圖」。