當(dāng)前位置:
首頁 >
前端技术
> javascript
>内容正文
javascript
JavaScript定义类的几种方式
生活随笔
收集整理的這篇文章主要介紹了
JavaScript定义类的几种方式
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
1.工廠方式 javaScript中創(chuàng)建自己的類和對象,我們應(yīng)該是必須掌握的,我們都知道javaScript中對象的屬性可以在對象創(chuàng)建后動態(tài)定義,比如下面的代碼: <script type="text/javascript">
??? //定義
??? var oCar = new Object();
??? oCar.color = "red";
??? oCar.doors = 4;
??? oCar.showColor = function() {
??????? alert(this.color);
??? }
??? //調(diào)用
??? oCar.showColor();
</script> 我們很容易使用oCar對象,但是我們創(chuàng)就是想創(chuàng)建多個Car實例。我們可以使用一個函數(shù)來封裝上面的代碼來實現(xiàn):<script type="text/javascript">
??? //定義
??? function createCar() {
??????? var oCar = new Object();
??????? oCar.color = "red";
??????? oCar.doors = 4;
??????? oCar.showColor = function() {
??????????? alert(this.color);
??????? }
??????? return oCar;
??? }
??? //調(diào)用
??? var ocar1 = createCar();
??? var ocar2 = createCar();
??? ocar1.color = "black";
??? ocar1.showColor();
??? ocar2.showColor();
</script> 順便說一下,javaScript對象默認(rèn)成員屬性都是public 的。這種方式我們稱為工廠方式,我們創(chuàng)造了能創(chuàng)建并返回特定類型的對象的工廠。 這樣做有點意思了,但是在面向?qū)ο笾形覀兘?jīng)常使用創(chuàng)建對象的方法是: Car car=new Car(); 使用new 關(guān)鍵字已經(jīng)深入人心,因此我們使用上面的方法去定義總感覺別扭,并且每次調(diào)用時都去創(chuàng)建新的屬性以及函數(shù),功能上也不實際。下來我們看看構(gòu)造函數(shù)的形式定義類。 2.構(gòu)造函數(shù) 這種方式看起來有點象工廠函數(shù)。具體表現(xiàn)如下: <script type="text/javascript">
??? //定義
??? function Car(color, doors) {
??????? this.color = color;
??????? this.doors = doors;
??????? this.showColor = function() {
??????????? alert(this.color);
??????? };
??? }
??? //調(diào)用
??? var car1 = new Car("red", 4);
??? var car2 = new Car("blue", 4);
??? car1.showColor();
??? car2.showColor();
</script> 看起來效果很明顯,有差別了吧。感覺有點意思了。在構(gòu)造函數(shù)內(nèi)部創(chuàng)造對象使用this 關(guān)鍵字,使用new 運算符創(chuàng)建對象感覺非常親切。但是也有點問題:每次new 對象時都會創(chuàng)建所有的屬性,包括函數(shù)的創(chuàng)建,也就是說多個對象完全獨立,我們定義類的目的就是為了共享方法以及數(shù)據(jù),但是car1對象與car2對象都是各自獨立的屬性與函數(shù),最起碼我們應(yīng)該共享方法。這就是原形方式的優(yōu)勢所在。 3.原型方式 利用對象的prototype屬性,可把它看出創(chuàng)建新對象所依賴的原型。方法如下: <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);
??? }
??? //調(diào)用:
??? var car1 = new Car();
??? var car2 = new Car();
??? car1.showColor();
??? car2.showColor();
??? alert(car1.drivers);
??? car1.drivers.push("stephen");
??? alert(car1.drivers); //結(jié)果:Tom,Jerry,stephen
??? alert(car2.drivers); //結(jié)果:Tom,Jerry,stephen //可以用json方式簡化prototype的定義: Car.prototype =
??????? {
??????????? color: "red",
??????????? doors: 4,
??????????? drivers: ["Tom", "Jerry",'safdad'],
??????????? showColor: function() {
??????????????? alert(this.color);
??????????? }
??????? }</script> 首先這段代碼的構(gòu)造函數(shù),其中沒有任何代碼,接下來通過對象的prototype屬性添加屬性定義Car對象的屬性。這種方法很好,但是問題是Car的對象指向的是Array指針,Car的兩個對象都指向同一個Array數(shù)組,其中一個對象car1改變屬性對象的引用(數(shù)組Array)時,另一個對象car2也同時改變,這是不允許的。 同時該問題也表現(xiàn)在原型不能帶任何初始化參數(shù),導(dǎo)致構(gòu)造函數(shù)無法正常初始化。這需要另一種方式來解決:那就是混合的構(gòu)造函數(shù)/原型模式。 4. 混合的構(gòu)造函數(shù)/原型模式 聯(lián)合使用構(gòu)造函數(shù)和原型方式,定義類就非常方便。 <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);
?? }
??
?? //調(diào)用:
?? 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); //結(jié)果:Tom,Jerry,stephen
?? alert(car2.drivers); //結(jié)果:Tom,Jerry
?? alert(car1 instanceof Car); </script> 該方法是把屬性放在內(nèi)部定義,把方法放在外邊利用prototype進(jìn)行定義。解決了第三種方法的問題。 這種方法其實應(yīng)該來說非常友好了,但是比起java的語法來,應(yīng)該有一些不和諧,感覺比較凌亂,對C++來說,我們就沒有那么麻煩的感覺了,可是開發(fā)C++的研發(fā)人員一般情況下很少涉及javaScript,而對J2EE的研發(fā)人員來說,這種方式總有一些別扭。總感覺不是友好的封裝,其實只不過是視覺上封裝效果不是很好而已,要想達(dá)到視覺封裝效果而又能達(dá)到這種方法的效果的也可以以,個人認(rèn)為其實比較麻煩。那就是動態(tài)原型法。 5.動態(tài)原型 對于習(xí)慣使用其他語言的開發(fā)者來說,使用混合的構(gòu)造函數(shù)/原型方式感覺不那么和諧。畢竟,定義類時,大多數(shù)面向?qū)ο笳Z言都對屬性和方法進(jìn)行了視覺上的封裝??紤]下面的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類的所有屬性和方法,因此看見這段代碼就知道它要實現(xiàn)什么功能,它定義了一個對象的信息。批評混合的構(gòu)造函數(shù)/原型方式的人認(rèn)為,在構(gòu)造函數(shù)內(nèi)存找屬性,在其外部找方法的做法不合邏輯。因此,他們設(shè)計了動態(tài)原型方法,以提供更友好的編碼風(fēng)格。 動態(tài)原型方法的基本想法與混合的構(gòu)造函數(shù)/原型方式相同,即在構(gòu)造函數(shù)內(nèi)定義非函數(shù)屬性,而函數(shù)屬性則利用原型屬性定義。唯一的區(qū)別是賦予對象方法的位置。下面是用動態(tài)原型方法重寫的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"之前,這個構(gòu)造函數(shù)都未發(fā)生變化。這行代碼是動態(tài)原型方法中最重要的部分。如果這個值未定義,構(gòu)造函數(shù)將用原型方式繼續(xù)定義對象的方法,然后把Car._initialized設(shè)置為true。如果這個值定義了(它的值為true時,typeof的值為Boolean),那么就不再創(chuàng)建該方法。簡而言之,該方法使用標(biāo)志(_initialized)來判斷是否已給原型賦予了任何方法。該方法只創(chuàng)建并賦值一次,為取悅傳統(tǒng)的OOP開發(fā)者,這段代碼看起來更像其他語言中的類定義了。 6? 混合工廠方式
這種方式通常是在不能應(yīng)用前一種方式時的變通方法。它的目的是創(chuàng)建假構(gòu)造函數(shù),只返回另一種對象的新實例。這段代碼看來與工廠函數(shù)非常相似: function Car() {
??????????? var oTempCar = new Object();
??????????? oTempCar.color="red";
??????????? oTempCar.doors=4;
??????????? oTempCar.mpg=23;
??????????? oTempCar.showColor = function() {
??????????????? alert(this.color);
??????????? }
??????????? return oTempCar;
??????? } 與經(jīng)典方式不同,這種方式使用new運算符,使它看起來像真正的構(gòu)造函數(shù):
var oCar = new Car();
由于在Car()構(gòu)造函數(shù)內(nèi)部調(diào)用了new運算符,所以將忽略第二個new運算符(位于構(gòu)造函數(shù)之外)。在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象被傳遞回變量var。這種方式在對象方法的內(nèi)部管理方面與經(jīng)典方式有著相同的問題。強(qiáng)烈建議:除非萬不得已(請參閱第15章),還是避免使用這種方式。
總結(jié):(采用哪種方式)
目前使用最廣泛的是混合的構(gòu)造函數(shù)/原型方式。此外,動態(tài)原型方法也很流行,在功能上與構(gòu)造函數(shù)/原型方式等價??梢圆捎眠@兩種方式中的任何一種。不過不要單獨使用經(jīng)典的構(gòu)造函數(shù)或原型方式,因為這樣會給代碼引入問題。
//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(); 本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/avon520/archive/2009/01/17/3819751.aspx
??? //定義
??? var oCar = new Object();
??? oCar.color = "red";
??? oCar.doors = 4;
??? oCar.showColor = function() {
??????? alert(this.color);
??? }
??? //調(diào)用
??? oCar.showColor();
</script> 我們很容易使用oCar對象,但是我們創(chuàng)就是想創(chuàng)建多個Car實例。我們可以使用一個函數(shù)來封裝上面的代碼來實現(xiàn):<script type="text/javascript">
??? //定義
??? function createCar() {
??????? var oCar = new Object();
??????? oCar.color = "red";
??????? oCar.doors = 4;
??????? oCar.showColor = function() {
??????????? alert(this.color);
??????? }
??????? return oCar;
??? }
??? //調(diào)用
??? var ocar1 = createCar();
??? var ocar2 = createCar();
??? ocar1.color = "black";
??? ocar1.showColor();
??? ocar2.showColor();
</script> 順便說一下,javaScript對象默認(rèn)成員屬性都是public 的。這種方式我們稱為工廠方式,我們創(chuàng)造了能創(chuàng)建并返回特定類型的對象的工廠。 這樣做有點意思了,但是在面向?qū)ο笾形覀兘?jīng)常使用創(chuàng)建對象的方法是: Car car=new Car(); 使用new 關(guān)鍵字已經(jīng)深入人心,因此我們使用上面的方法去定義總感覺別扭,并且每次調(diào)用時都去創(chuàng)建新的屬性以及函數(shù),功能上也不實際。下來我們看看構(gòu)造函數(shù)的形式定義類。 2.構(gòu)造函數(shù) 這種方式看起來有點象工廠函數(shù)。具體表現(xiàn)如下: <script type="text/javascript">
??? //定義
??? function Car(color, doors) {
??????? this.color = color;
??????? this.doors = doors;
??????? this.showColor = function() {
??????????? alert(this.color);
??????? };
??? }
??? //調(diào)用
??? var car1 = new Car("red", 4);
??? var car2 = new Car("blue", 4);
??? car1.showColor();
??? car2.showColor();
</script> 看起來效果很明顯,有差別了吧。感覺有點意思了。在構(gòu)造函數(shù)內(nèi)部創(chuàng)造對象使用this 關(guān)鍵字,使用new 運算符創(chuàng)建對象感覺非常親切。但是也有點問題:每次new 對象時都會創(chuàng)建所有的屬性,包括函數(shù)的創(chuàng)建,也就是說多個對象完全獨立,我們定義類的目的就是為了共享方法以及數(shù)據(jù),但是car1對象與car2對象都是各自獨立的屬性與函數(shù),最起碼我們應(yīng)該共享方法。這就是原形方式的優(yōu)勢所在。 3.原型方式 利用對象的prototype屬性,可把它看出創(chuàng)建新對象所依賴的原型。方法如下: <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);
??? }
??? //調(diào)用:
??? var car1 = new Car();
??? var car2 = new Car();
??? car1.showColor();
??? car2.showColor();
??? alert(car1.drivers);
??? car1.drivers.push("stephen");
??? alert(car1.drivers); //結(jié)果:Tom,Jerry,stephen
??? alert(car2.drivers); //結(jié)果:Tom,Jerry,stephen //可以用json方式簡化prototype的定義: Car.prototype =
??????? {
??????????? color: "red",
??????????? doors: 4,
??????????? drivers: ["Tom", "Jerry",'safdad'],
??????????? showColor: function() {
??????????????? alert(this.color);
??????????? }
??????? }</script> 首先這段代碼的構(gòu)造函數(shù),其中沒有任何代碼,接下來通過對象的prototype屬性添加屬性定義Car對象的屬性。這種方法很好,但是問題是Car的對象指向的是Array指針,Car的兩個對象都指向同一個Array數(shù)組,其中一個對象car1改變屬性對象的引用(數(shù)組Array)時,另一個對象car2也同時改變,這是不允許的。 同時該問題也表現(xiàn)在原型不能帶任何初始化參數(shù),導(dǎo)致構(gòu)造函數(shù)無法正常初始化。這需要另一種方式來解決:那就是混合的構(gòu)造函數(shù)/原型模式。 4. 混合的構(gòu)造函數(shù)/原型模式 聯(lián)合使用構(gòu)造函數(shù)和原型方式,定義類就非常方便。 <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);
?? }
??
?? //調(diào)用:
?? 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); //結(jié)果:Tom,Jerry,stephen
?? alert(car2.drivers); //結(jié)果:Tom,Jerry
?? alert(car1 instanceof Car); </script> 該方法是把屬性放在內(nèi)部定義,把方法放在外邊利用prototype進(jìn)行定義。解決了第三種方法的問題。 這種方法其實應(yīng)該來說非常友好了,但是比起java的語法來,應(yīng)該有一些不和諧,感覺比較凌亂,對C++來說,我們就沒有那么麻煩的感覺了,可是開發(fā)C++的研發(fā)人員一般情況下很少涉及javaScript,而對J2EE的研發(fā)人員來說,這種方式總有一些別扭。總感覺不是友好的封裝,其實只不過是視覺上封裝效果不是很好而已,要想達(dá)到視覺封裝效果而又能達(dá)到這種方法的效果的也可以以,個人認(rèn)為其實比較麻煩。那就是動態(tài)原型法。 5.動態(tài)原型 對于習(xí)慣使用其他語言的開發(fā)者來說,使用混合的構(gòu)造函數(shù)/原型方式感覺不那么和諧。畢竟,定義類時,大多數(shù)面向?qū)ο笳Z言都對屬性和方法進(jìn)行了視覺上的封裝??紤]下面的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類的所有屬性和方法,因此看見這段代碼就知道它要實現(xiàn)什么功能,它定義了一個對象的信息。批評混合的構(gòu)造函數(shù)/原型方式的人認(rèn)為,在構(gòu)造函數(shù)內(nèi)存找屬性,在其外部找方法的做法不合邏輯。因此,他們設(shè)計了動態(tài)原型方法,以提供更友好的編碼風(fēng)格。 動態(tài)原型方法的基本想法與混合的構(gòu)造函數(shù)/原型方式相同,即在構(gòu)造函數(shù)內(nèi)定義非函數(shù)屬性,而函數(shù)屬性則利用原型屬性定義。唯一的區(qū)別是賦予對象方法的位置。下面是用動態(tài)原型方法重寫的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"之前,這個構(gòu)造函數(shù)都未發(fā)生變化。這行代碼是動態(tài)原型方法中最重要的部分。如果這個值未定義,構(gòu)造函數(shù)將用原型方式繼續(xù)定義對象的方法,然后把Car._initialized設(shè)置為true。如果這個值定義了(它的值為true時,typeof的值為Boolean),那么就不再創(chuàng)建該方法。簡而言之,該方法使用標(biāo)志(_initialized)來判斷是否已給原型賦予了任何方法。該方法只創(chuàng)建并賦值一次,為取悅傳統(tǒng)的OOP開發(fā)者,這段代碼看起來更像其他語言中的類定義了。 6? 混合工廠方式
這種方式通常是在不能應(yīng)用前一種方式時的變通方法。它的目的是創(chuàng)建假構(gòu)造函數(shù),只返回另一種對象的新實例。這段代碼看來與工廠函數(shù)非常相似: function Car() {
??????????? var oTempCar = new Object();
??????????? oTempCar.color="red";
??????????? oTempCar.doors=4;
??????????? oTempCar.mpg=23;
??????????? oTempCar.showColor = function() {
??????????????? alert(this.color);
??????????? }
??????????? return oTempCar;
??????? } 與經(jīng)典方式不同,這種方式使用new運算符,使它看起來像真正的構(gòu)造函數(shù):
var oCar = new Car();
由于在Car()構(gòu)造函數(shù)內(nèi)部調(diào)用了new運算符,所以將忽略第二個new運算符(位于構(gòu)造函數(shù)之外)。在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對象被傳遞回變量var。這種方式在對象方法的內(nèi)部管理方面與經(jīng)典方式有著相同的問題。強(qiáng)烈建議:除非萬不得已(請參閱第15章),還是避免使用這種方式。
總結(jié):(采用哪種方式)
目前使用最廣泛的是混合的構(gòu)造函數(shù)/原型方式。此外,動態(tài)原型方法也很流行,在功能上與構(gòu)造函數(shù)/原型方式等價??梢圆捎眠@兩種方式中的任何一種。不過不要單獨使用經(jīng)典的構(gòu)造函數(shù)或原型方式,因為這樣會給代碼引入問題。
//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(); 本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/avon520/archive/2009/01/17/3819751.aspx
轉(zhuǎn)載于:https://blog.51cto.com/fluagen/303152
總結(jié)
以上是生活随笔為你收集整理的JavaScript定义类的几种方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一个H3CNE测试的配置
- 下一篇: windowsXP/7下消除快捷键箭头的