[轉(zhuǎn)]JavaScript面向?qū)ο蟮奶匦?/a>
如果你使用JavaScript編程,你或許會(huì)懷疑它是否包含了面向?qū)ο螅∣O)的結(jié)構(gòu)。實(shí)際上,JavaScript的確支持面向?qū)ο蟮募軜?gòu)――在某種程度上。本文將通過一個(gè)可擴(kuò)展向量圖形(SVG)的實(shí)例來說明JavaScript的OO結(jié)構(gòu)。我如何在類中定義方法和屬性?
OO開發(fā)的一個(gè)基本方面是類及其相應(yīng)的方法和/或?qū)傩缘氖褂谩avaScript通過function關(guān)鍵字支持類(及其屬性)的使用。下面的代碼定義了一個(gè)叫做Figure的JavaScript類:
function Figure() {
this.centerX=0;
this.centerY=0;
this.area=0;
this.transform = transform; // methods are defined like this
function transform(moveX,moveY,angle) {
this.centerX += moveX;
this.centerY += moveY;
} }
這個(gè)Figure類有三個(gè)屬性:centerX,centerY,和area。另外,它還有一個(gè)方法叫做transform()。前三行是這個(gè)類的構(gòu)造器。
但是它看起來不像一個(gè)類
你會(huì)想Figure()看起來不像一個(gè)類,而更像一個(gè)JavaScript的函數(shù)。那么為什么Figure()定義的是個(gè)類?
嚴(yán)格的說,F(xiàn)igure()函數(shù)沒有定義一個(gè)類,但是它仿造了一個(gè)。它實(shí)際上創(chuàng)建了一個(gè)對(duì)象,在括號(hào)里的代碼使這個(gè)對(duì)象的構(gòu)造器。JavaScript的對(duì)象支持是很基礎(chǔ)的,它并不區(qū)分類和對(duì)象。
這就引到了問題為什么Figure()函數(shù)創(chuàng)建的是一個(gè)對(duì)象。對(duì)象是可以有屬性和方法的。基本上,因?yàn)镕igure()函數(shù)同時(shí)包含了屬性和方法,它就是個(gè)對(duì)象。在JavaScript里,所有的函數(shù)即是對(duì)象又是可調(diào)用的代碼塊。這不像它聽起來的那樣容易被誤解。要?jiǎng)?chuàng)建一個(gè)Figure()類/對(duì)象,你只用使用以下句法:
MyFigure = new Figure();
你也可以把Figure()函數(shù)當(dāng)作代碼塊調(diào)用,就像這樣:
figValue = Figure();
變量figValue沒有被定義是因?yàn)榇a塊Figure()沒有返回任何值。如果你把return(this.area)加到函數(shù)的最后一行,figValue就會(huì)有個(gè)值0。所以figValue是個(gè)類型數(shù)字,MyFigure是對(duì)象 Rectangle的實(shí)例。
為什么所有的變量前面都一個(gè)“this”?
這個(gè)關(guān)鍵字this表示這是對(duì)象的實(shí)例變量,可以使用MyFigure.centerX從對(duì)象外部訪問。要讓變量成為私有變量,去掉前綴this就行了。this.transform = transform這一行讓方法成為公用方法。這個(gè)方法通過MyFigure.transform(100,100,0)調(diào)用。
這些類有層次之分嗎?另一個(gè)好問題的是JavaScript的類是否有層次之分。回答是肯定有。我們來仔細(xì)看看是怎么做到分層的。我們可以定義一個(gè)Rectangle子類,并把Figure作為父類:
function Rectangle(startX, startY, endX, endY) {
this.width = endX - startX;
this.height = endY - startY;
this.centerX = (endX + startX)/2;
this.centerY = (endY + startY)/2;
this.computeArea = computeArea;
function computeArea() {
this.area = this.width*this.height;
} }
Rectangle.prototype = new Figure();
Rectangle對(duì)象是用4個(gè)自變量創(chuàng)建的,前四行是構(gòu)造器。 Rectangle類包含了一個(gè)方法: computeArea()。最后一行Rectangle.prototype = new Figure();,把Rectangle類定義為從Figure類繼承來的子類。
然我來解釋一下prototype(原型)。每個(gè)對(duì)象構(gòu)造器都有prototype屬性;這是用來給所有的對(duì)象增加新屬性和方法的。這就是為什么原型被用來實(shí)現(xiàn)繼承:child.prototype = new parent();。通過原型,父對(duì)象的所有屬性和方法都被添加到子對(duì)象上。
要注意this.centerX,this.centerY,和area是Rectangle類中所使用的屬性,但是它們是 Figure父類的屬性。和Rectangle類相似,Circle類可以被定義成Figure類的原型。這種父子關(guān)系可以按你需要來定義深度;你可以創(chuàng)建另一個(gè)Rectangle的子類。
我如何創(chuàng)建一個(gè)類的實(shí)例?
在JavaScript里創(chuàng)建一個(gè)類的實(shí)例很容易:
rect = new Rectangle(100,100,900,800);
這就創(chuàng)建了Rectangle類型的一個(gè)對(duì)象。Rectangle的構(gòu)造器在屬性width, height, centerX, 和centerY中填入了值。rect.area屬性的值是零(0)。使用這個(gè)命令就能調(diào)用area方法:
rect.computeArea();
rect.area的值現(xiàn)在是560,000。要調(diào)用transform方法使用:
rect.transform(100,200,0);
父和子對(duì)象的屬性可以像這樣訪問到:
var ar = rect.area;
var wi = rect.width;
我能超越屬性和方法嗎?
就像你在Java中的一樣,你可以超越屬性和方法。在子類中定義的屬性或者方法可以超越同名的父類的屬性和方法。
和全局變量互動(dòng)
JavaScript也支持全局變量的使用。在以下代碼段中測(cè)試一下g_area變量的范圍:
<HTML>
<SCRIPT>
var g_area = 20;
function Figure() {
…
this.area=g_area;
…
}
function Rectangle(){ … }
Rectangle.prototype = new Figure();
function test(){
g_area = 40;
rect = new Rectangle();
alert(rect.area);
}
</SCRIPT>
<BODY onLoad = 'test()'/>
</BODY>
</HTML>
rect.area的值是20(不是你預(yù)計(jì)的40),這是因?yàn)镽ectangle對(duì)象是Figure對(duì)象的原型,這種關(guān)系在test()被調(diào)用以前就被定義了。要使用g_area的新值,你需要用以下的方法:
function test() {
g_area = 40;
Rectangle.prototype = new Figure();
rect = new Rectangle();
alert(rect.area);
}
對(duì)于所有的Rectangle的新實(shí)例,這將改變area屬性的值。或者,你可以使用這種方法:function test() {
g_area = 40;
rect = new Rectangle();
Rectangle.prototype.area = g_area;
alert(rect.area);
}
這將改變Rectangle所有現(xiàn)存的以及新實(shí)例的area屬性的值。
結(jié)論
為了效仿OO開發(fā),JavaScript提供了必需的繼承、封裝和超越屬性,盡管它不支持接口和方法的過載。如果你是剛接觸到OO開發(fā),用它試試。OO概念允許開發(fā)者將一組數(shù)據(jù)和相關(guān)操作集中入一個(gè)對(duì)象。這在管理瀏覽器事件和管理瀏覽器內(nèi)SVG圖時(shí)很有用。
posted on 2006-08-30 09:37 sunfruit 閱讀(405) 評(píng)論(0) 編輯 收藏 所屬分類: JAVASCRIPT