javascript 的物件導向特性參考

來源:互聯網
上載者:User

javascript 的物件導向特性參考。
這是我學習javascript中物件導向特性的一點總結。希望對具有其他語言的物件導向設計經驗的朋友理解javascript的OO有所協助。我具有c++,java和python的物件導向設計的經驗。
總的感受, javascript作為一種弱類型的動態語言,文法解決於java,但其物件導向的方式更和python相識。
1 物件導向的特性
類,成員變數,成員函數,類變數,類方法,繼承,多態
1) 類
類的定義:function Circle(r) { this.r = r; }
類的執行個體化: c = Circle(3);
2)成員變數
成員變數在初始化函數裡申明:this.r = r;
注意,在對象產生後,你也可以給它附上成員變數,比如c.name="my circle",
但是除非特別的需要,我強烈建議你不要這樣做。也就是所有的成員都應在初始化函數裡聲明。我認為這是一種好的style。
這一點和python很相識。
3)成員函數
成員函數的標準形式是這樣的:
Cricle.prototype.area = function() { return 3.14 * this.r * this.r; }
這和java或python或c++都大不一樣。但為了協助理解,你可以把prototype看作基類。
prototype裡面的變數或方法,是所有對象共用的。
比如,c.area()調用最終就會讓解譯器調用到Circle.prototype.area().
相比於java和c++,javascript具有他們都沒有的一個語義,也就是你可以在prototype裡定義變數。定義在prototype裡的變數可以被所有的執行個體共用量。所以一般它應該是一個常數,比如:Circle.prototype.PI = 3.14.
顯然,prototype裡的變數和方法都應該是不變的。每一個對象執行個體都不應該取修改prototype中的內容。雖然語言允許你可以這樣做,但這樣做沒有任何意義,也違反了物件導向的語義(想想,java會讓你動態修改一個類的方法嗎)。
當然,對於多態是另外一回事,在後面詳述。
而且,我建議所有的成員函數都在緊接類定義的地方定義。而不應該在代碼啟動並執行某個地方對一個對象執行個體增加/修改成員函數。這樣的結果是javascript的類定義盡量向java看齊。使得代碼更清晰。
4)類變數
類變數是屬於一個類的變數。就像java裡用static修飾的變數。因為它屬於類,所以它也應該是一個常量。執行個體不應該去修改它,雖然你可以(java裡可以用final修飾,使得類變數一旦定義,就不能修改)。
這裡可以看到,類變數和prototype裡定義的變數的功能是相似的。確實如此,他們的目的都是一樣的。但他們的訪問方式
不一樣。比如:
Circle.prototype.PI = 3.14;
Circle.PI = 3.14;
//用prototype裡的變數
Circle.prototype.area1 = function() { return this.PI * this.r * this.r; }
//用類變數
Circle.prototype.area2 = function() { return Circle.PI * this.r * this.r; }
5)類方法
這個概念應該很簡單。注意類方法裡絕對不要用this關鍵字,和java完全一樣。
Circle.max = function(a, b) { return a.r > b.r ? a : b; }
theMax = Circle(new Circle(1), new Circle(4));
6)繼承
子類繼承父類,那麼 “子類執行個體” 具有和 “父類執行個體” 完全一樣的行為。javascript是這樣實現的。
function SubCircle(x, y, r) { this.x = x; this.y = y; this.r =r; }
SubCircle.prototype = new Circle(0);
記得前面說的嗎?可以把prototype看作一個基類。這裡,prototype確確實實是一個基類。它是如何?的呢?
舉例如下:sc = SubCirlce(1,1,3); sc.area();
調用的傳遞: sc.area()->sc.prototype.area()->Circle(0).area()->Circle.prototype.area().看來是不是很奇妙呢。
通過這種方式,javascript實現了繼承。
7)多態
多態是子類會定義和父類具有相同signature的方法。假設在SubCircle所在的空間PI=100,而面積公式也變為 PI*R*R*R。
SubCircle.prototype.PI = 100
SubCircle.prototype.area = function() { return this.PI*this.r*this.r*this.r; }
Sc.area() 這樣的操作可以認為是:
Sc.PI->sc.prototype.PI->Cricle(0).PI = 100
Sc.area()->sc.prototype.area()->Circle(0).area.
這個時候,調用過程是這樣的
sc.area()->sc.prototype.area(),在這裡解譯器發現了area這個方法,於是它就調用此方法。
而Cricle.prototype.area就永遠也不會被調用。PI的調用也是如此。
那麼子類如何想調用父類的方法應怎麼辦呢?好像沒有什麼辦法哦,誰知道可以告訴我。但物件導向的理論告訴我們,繼承主要是提供介面而不是代碼複用,所以還是少有這樣的念頭為好 :)。
下面是一個例子程式。包含上面的所有的概念。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.