JavaScript定義類的幾種方式總結

來源:互聯網
上載者:User

 本篇文章主要是對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">        //定義        function Car() {            this.color = "red";            this.doors = 4;            this.drivers = new Array("Tom", "Jerry");            if (typeof Car._initialized == "undefined") {                Car.prototype.showColor = function() {                    alert(this.color);                }                //............            }            //最後定義            Car._initialized = true;        }    </script> 直到檢查typeof Car._initialized是否等於"undefined"之前,這個建構函式都未發生變化。這行代碼是動態原型方法中最重要的部分。如果這個值未定義,建構函式將用原型方式繼續定義對象的方法,然後把Car._initialized設定為true。如果這個值定義了(它的值為true時,typeof的值為Boolean),那麼就不再建立該方法。簡而言之,該方法使用標誌(_initialized)來判斷是否已給原型賦予了任何方法。該方法只建立並賦值一次,為取悅傳統的OOP開發人員,這段代碼看起來更像其他語言中的類定義了。 6  混合工廠方式 這種方式通常是在不能應用前一種方式時的變通方法。它的目的是建立假建構函式,只返回另一種對象的新執行個體。這段代碼看來與工廠函數非常相似:代碼如下:function Car() {            var oTempCar = new Object();            oTempCar.color="red";            oTempCar.doors=4;            oTempCar.mpg=23;            oTempCar.showColor = function() {                alert(this.color);            }            return oTempCar;        } 與經典方式不同,這種方式使用new運算子,使它看起來像真正的建構函式:var oCar = new Car(); 由於在Car()建構函式內部調用了new運算子,所以將忽略第二個new運算子(位於建構函式之外)。在建構函式內部建立的對象被傳遞迴變數var。這種方式在對象方法的內部管理方面與經典方式有著相同的問題。強烈建議:除非萬不得已(請參閱第15章),還是避免使用這種方式。 總結:(採用哪種方式)目前使用最廣泛的是混合的建構函式/原型方式。此外,動態原型方法也很流行,在功能上與建構函式/原型方式等價。可以採用這兩種方式中的任何一種。不過不要單獨使用經典的建構函式或原型方式,因為這樣會給代碼引入問題。 代碼如下://ps//static class (1:function)    var CarCollection = new function() {        var _carCollection = new Array(); //global,private        this.Add = function(objCar) {            alert('Add');        }        this.Get = function(carid) {            alert('Get');        }    } //static class (2:json)      var Car = {        color: 'red',        doors: 4,        showColor: function() { alert(this.color); }    }    Car.showColor(); 
相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

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

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