萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> JavaScript定義類的幾種方式總結

JavaScript定義類的幾種方式總結

 本篇文章主要是對JavaScript定義類的幾種方式進行了詳細的總結介紹,需要的朋友可以過來參考下,希望對大家有所幫助

提起面向對象我們就能想到類,對象,封裝,繼承,多態。在《javaScript高級程序設計》(人民郵電出版社,曹力、張欣譯。英文名字是:Professional JavaScript for Web Developers)這本書中描述的還算比較詳細。我們看看JavaScript中定義類的各種方法。    1.工廠方式   javaScript中創建自己的類和對象,我們應該是必須掌握的,我們都知道javaScript中對象的屬性可以在對象創建後動態定義,比如下面的代碼:    代碼如下: <script type="text/javascript">     //定義     var oCar = new Object();     oCar.color = "red";     oCar.doors = 4;     oCar.showColor = function() {         alert(this.color);     }     //調用     oCar.showColor(); </script>    我們很容易使用oCar對象,但是我們創就是想創建多個Car實例。我們可以使用一個函數來封裝上面的代碼來實現: 復制代碼 代碼如下: <script type="text/javascript">     //定義     function createCar() {         var oCar = new Object();         oCar.color = "red";         oCar.doors = 4;         oCar.showColor = function() {             alert(this.color);         }         return oCar;     }     //調用     var ocar1 = createCar();     var ocar2 = createCar();     ocar1.color = "black";     ocar1.showColor();     ocar2.showColor(); </script>   順便說一下,javaScript對象默認成員屬性都是public 的。這種方式我們稱為工廠方式,我們創造了能創建並返回特定類型的對象的工廠。   這樣做有點意思了,但是在面向對象中我們經常使用創建對象的方法是:   Car car=new Car();   使用new 關鍵字已經深入人心,因此我們使用上面的方法去定義總感覺別扭,並且每次調用時都去創建新的屬性以及函數,功能上也不實際。下來我們看看構造函數的形式定義類。   2.構造函數   這種方式看起來有點象工廠函數。具體表現如下:  代碼如下: <script type="text/javascript">     //定義     function Car(color, doors) {         this.color = color;         this.doors = doors;         this.showColor = function() {             alert(this.color);         };     }     //調用     var car1 = new Car("red", 4);     var car2 = new Car("blue", 4);     car1.showColor();     car2.showColor(); </script>    看起來效果很明顯,有差別了吧。感覺有點意思了。在構造函數內部創造對象使用this 關鍵字,使用new 運算符創建對象感覺非常親切。但是也有點問題:每次new 對象時都會創建所有的屬性,包括函數的創建,也就是說多個對象完全獨立,我們定義類的目的就是為了共享方法以及數據,但是car1對象與car2對象都是各自獨立的屬性與函數,最起碼我們應該共享方法。這就是原形方式的優勢所在。   3.原型方式   利用對象的prototype屬性,可把它看出創建新對象所依賴的原型。方法如下:   代碼如下: <script type="text/javascript">     //定義     function Car() {     };     Car.prototype.color = "red";     Car.prototype.doors = 4;     Car.prototype.drivers = new Array("Tom", "Jerry");     Car.prototype.showColor = function() {         alert(this.color);     }     //調用:     var car1 = new Car();     var car2 = new Car();     car1.showColor();     car2.showColor();     alert(car1.drivers);     car1.drivers.push("stephen");     alert(car1.drivers); //結果:Tom,Jerry,stephen     alert(car2.drivers); //結果:Tom,Jerry,stephen       //可以用json方式簡化prototype的定義:           Car.prototype =         {             color: "red",             doors: 4,             drivers: ["Tom", "Jerry",'safdad'],             showColor: function() {                 alert(this.color);             }         } </script>     首先這段代碼的構造函數,其中沒有任何代碼,接下來通過對象的prototype屬性添加屬性定義Car對象的屬性。這種方法很好,但是問題是Car的對象指向的是Array指針,Car的兩個對象都指向同一個Array數組,其中一個對象car1改變屬性對象的引用(數組Array)時,另一個對象car2也同時改變,這是不允許的。   同時該問題也表現在原型不能帶任何初始化參數,導致構造函數無法正常初始化。這需要另一種方式來解決:那就是混合的構造函數/原型模式。   4. 混合的構造函數/原型模式   聯合使用構造函數和原型方式,定義類就非常方便。   代碼如下: <script type="text/javascript"> //定義     function Car(color,doors)    {         this.color=color;         this.doors=doors;         this.drivers=new Array("Tom","Jerry");    }      Car.prototype.showColor=function(){         alert(this.color);    }      //調用:    var car1=new Car('red',4);    var car2=new Car('blue',4);      car1.showColor();    car2.showColor();      alert(car1.drivers);    car1.drivers.push("stephen");    alert(car1.drivers); //結果:Tom,Jerry,stephen    alert(car2.drivers); //結果:Tom,Jerry    alert(car1 instanceof Car);   </script>     該方法是把屬性放在內部定義,把方法放在外邊利用prototype進行定義。解決了第三種方法的問題。   這種方法其實應該來說非常友好了,但是比起java的語法來,應該有一些不和諧,感覺比較凌亂,對C++來說,我們就沒有那麼麻煩的感覺了,可是開發C++的研發人員一般情況下很少涉及javaScript,而對J2EE的研發人員來說,這種方式總有一些別扭。總感覺不是友好的封裝,其實只不過是視覺上封裝效果不是很好而已,要想達到視覺封裝效果而又能達到這種方法的效果的也可以以,個人認為其實比較麻煩。那就是動態原型法。   5.動態原型   對於習慣使用其他語言的開發者來說,使用混合的構造函數/原型方式感覺不那麼和諧。畢竟,定義類時,大多數面向對象語言都對屬性和方法進行了視覺上的封裝。考慮下面的C#類:  代碼如下: class Car //class {     public string color = "red";     public int doors = 4;     public int mpg = 23;       public Car(string color, int doors, int mpg) //constructor     {         this.color = color;         this.doors = doors;         this.mpg = mpg;     }     public void showColor() //method     {         Console.WriteLine(this.color);     } }     C#很好的打包了Car類的所有屬性和方法,因此看見這段代碼就知道它要實現什麼功能,它定義了一個對象的信息。批評混合的構造函數/原型方式的人認為,在構造函數內存找屬性,在其外部找方法的做法不合邏輯。因此,他們設計了動態原型方法,以提供更友好的編碼風格。   動態原型方法的基本想法與混合的構造函數/原型方式相同,即在構造函數內定義非函數屬性,而函數屬性則利用原型屬性定義。唯一的區別是賦予對象方法的位置。下面是用動態原型方法重寫的Car類:    代碼如下:     <script type="text/javascript">    
copyright © 萬盛學電腦網 all rights reserved