欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JavaScript定義類或函數(shù)的幾種方式小結(jié)

 更新時(shí)間:2011年01月09日 17:07:16   作者:  
js中不論是定義類或者函數(shù),很多朋友想將代碼寫(xiě)的更專業(yè),更方便擴(kuò)展等,那么就可以參考這篇文章了,最好是總結(jié),建議大家收藏下。
提起面向?qū)ο笪覀兙湍芟氲筋?,?duì)象,封裝,繼承,多態(tài)。在《javaScript高級(jí)程序設(shè)計(jì)》(人民郵電出版社,曹力、張欣譯。英文名字是:Professional JavaScript for Web Developers)這本書(shū)中描述的還算比較詳細(xì)。我們看看JavaScript中定義類的各種方法。
1.工廠方式
javaScript中創(chuàng)建自己的類和對(duì)象,我們應(yīng)該是必須掌握的,我們都知道javaScript中對(duì)象的屬性可以在對(duì)象創(chuàng)建后動(dòng)態(tài)定義,比如下面的代碼:
復(fù)制代碼 代碼如下:

<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對(duì)象,但是我們創(chuàng)就是想創(chuàng)建多個(gè)Car實(shí)例。我們可以使用一個(gè)函數(shù)來(lái)封裝上面的代碼來(lái)實(shí)現(xiàn):<script type="text/javascript">
復(fù)制代碼 代碼如下:

//定義
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>

順便說(shuō)一下,javaScript對(duì)象默認(rèn)成員屬性都是public 的。這種方式我們稱為工廠方式,我們創(chuàng)造了能創(chuàng)建并返回特定類型的對(duì)象的工廠。
這樣做有點(diǎn)意思了,但是在面向?qū)ο笾形覀兘?jīng)常使用創(chuàng)建對(duì)象的方法是:
Car car=new Car();
使用new 關(guān)鍵字已經(jīng)深入人心,因此我們使用上面的方法去定義總感覺(jué)別扭,并且每次調(diào)用時(shí)都去創(chuàng)建新的屬性以及函數(shù),功能上也不實(shí)際。下來(lái)我們看看構(gòu)造函數(shù)的形式定義類。
2.構(gòu)造函數(shù)
這種方式看起來(lái)有點(diǎn)象工廠函數(shù)。具體表現(xiàn)如下:
復(fù)制代碼 代碼如下:

<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>

看起來(lái)效果很明顯,有差別了吧。感覺(jué)有點(diǎn)意思了。在構(gòu)造函數(shù)內(nèi)部創(chuàng)造對(duì)象使用this 關(guān)鍵字,使用new 運(yùn)算符創(chuàng)建對(duì)象感覺(jué)非常親切。但是也有點(diǎn)問(wèn)題:每次new 對(duì)象時(shí)都會(huì)創(chuàng)建所有的屬性,包括函數(shù)的創(chuàng)建,也就是說(shuō)多個(gè)對(duì)象完全獨(dú)立,我們定義類的目的就是為了共享方法以及數(shù)據(jù),但是car1對(duì)象與car2對(duì)象都是各自獨(dú)立的屬性與函數(shù),最起碼我們應(yīng)該共享方法。這就是原形方式的優(yōu)勢(shì)所在。
3.原型方式
利用對(duì)象的prototype屬性,可把它看出創(chuàng)建新對(duì)象所依賴的原型。方法如下:
復(fù)制代碼 代碼如下:

<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方式簡(jiǎn)化prototype的定義:
Car.prototype =
{
color: "red",
doors: 4,
drivers: ["Tom", "Jerry",'safdad'],
showColor: function() {
alert(this.color);
}
}</script>

首先這段代碼的構(gòu)造函數(shù),其中沒(méi)有任何代碼,接下來(lái)通過(guò)對(duì)象的prototype屬性添加屬性定義Car對(duì)象的屬性。這種方法很好,但是問(wèn)題是Car的對(duì)象指向的是Array指針,Car的兩個(gè)對(duì)象都指向同一個(gè)Array數(shù)組,其中一個(gè)對(duì)象car1改變屬性對(duì)象的引用(數(shù)組Array)時(shí),另一個(gè)對(duì)象car2也同時(shí)改變,這是不允許的。
同時(shí)該問(wèn)題也表現(xiàn)在原型不能帶任何初始化參數(shù),導(dǎo)致構(gòu)造函數(shù)無(wú)法正常初始化。這需要另一種方式來(lái)解決:那就是混合的構(gòu)造函數(shù)/原型模式。
4. 混合的構(gòu)造函數(shù)/原型模式
聯(lián)合使用構(gòu)造函數(shù)和原型方式,定義類就非常方便。
復(fù)制代碼 代碼如下:

<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)行定義。解決了第三種方法的問(wèn)題。
這種方法其實(shí)應(yīng)該來(lái)說(shuō)非常友好了,但是比起java的語(yǔ)法來(lái),應(yīng)該有一些不和諧,感覺(jué)比較凌亂,對(duì)C++來(lái)說(shuō),我們就沒(méi)有那么麻煩的感覺(jué)了,可是開(kāi)發(fā)C++的研發(fā)人員一般情況下很少涉及javaScript,而對(duì)J2EE的研發(fā)人員來(lái)說(shuō),這種方式總有一些別扭。總感覺(jué)不是友好的封裝,其實(shí)只不過(guò)是視覺(jué)上封裝效果不是很好而已,要想達(dá)到視覺(jué)封裝效果而又能達(dá)到這種方法的效果的也可以以,個(gè)人認(rèn)為其實(shí)比較麻煩。那就是動(dòng)態(tài)原型法。
5.動(dòng)態(tài)原型
對(duì)于習(xí)慣使用其他語(yǔ)言的開(kāi)發(fā)者來(lái)說(shuō),使用混合的構(gòu)造函數(shù)/原型方式感覺(jué)不那么和諧。畢竟,定義類時(shí),大多數(shù)面向?qū)ο笳Z(yǔ)言都對(duì)屬性和方法進(jìn)行了視覺(jué)上的封裝??紤]下面的C#類:
復(fù)制代碼 代碼如下:

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類的所有屬性和方法,因此看見(jiàn)這段代碼就知道它要實(shí)現(xiàn)什么功能,它定義了一個(gè)對(duì)象的信息。批評(píng)混合的構(gòu)造函數(shù)/原型方式的人認(rèn)為,在構(gòu)造函數(shù)內(nèi)存找屬性,在其外部找方法的做法不合邏輯。因此,他們?cè)O(shè)計(jì)了動(dòng)態(tài)原型方法,以提供更友好的編碼風(fēng)格。
動(dòng)態(tài)原型方法的基本想法與混合的構(gòu)造函數(shù)/原型方式相同,即在構(gòu)造函數(shù)內(nèi)定義非函數(shù)屬性,而函數(shù)屬性則利用原型屬性定義。唯一的區(qū)別是賦予對(duì)象方法的位置。下面是用動(dòng)態(tài)原型方法重寫(xiě)的Car類:
復(fù)制代碼 代碼如下:

<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è)構(gòu)造函數(shù)都未發(fā)生變化。這行代碼是動(dòng)態(tài)原型方法中最重要的部分。如果這個(gè)值未定義,構(gòu)造函數(shù)將用原型方式繼續(xù)定義對(duì)象的方法,然后把Car._initialized設(shè)置為true。如果這個(gè)值定義了(它的值為true時(shí),typeof的值為Boolean),那么就不再創(chuàng)建該方法。簡(jiǎn)而言之,該方法使用標(biāo)志(_initialized)來(lái)判斷是否已給原型賦予了任何方法。該方法只創(chuàng)建并賦值一次,為取悅傳統(tǒng)的OOP開(kāi)發(fā)者,這段代碼看起來(lái)更像其他語(yǔ)言中的類定義了。
6 混合工廠方式

這種方式通常是在不能應(yīng)用前一種方式時(shí)的變通方法。它的目的是創(chuàng)建假構(gòu)造函數(shù),只返回另一種對(duì)象的新實(shí)例。這段代碼看來(lái)與工廠函數(shù)非常相似:
復(fù)制代碼 代碼如下:

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運(yùn)算符,使它看起來(lái)像真正的構(gòu)造函數(shù):
var oCar = new Car();

由于在Car()構(gòu)造函數(shù)內(nèi)部調(diào)用了new運(yùn)算符,所以將忽略第二個(gè)new運(yùn)算符(位于構(gòu)造函數(shù)之外)。在構(gòu)造函數(shù)內(nèi)部創(chuàng)建的對(duì)象被傳遞回變量var。這種方式在對(duì)象方法的內(nèi)部管理方面與經(jīng)典方式有著相同的問(wèn)題。強(qiáng)烈建議:除非萬(wàn)不得已(請(qǐng)參閱第15章),還是避免使用這種方式。
總結(jié):(采用哪種方式)
目前使用最廣泛的是混合的構(gòu)造函數(shù)/原型方式。此外,動(dòng)態(tài)原型方法也很流行,在功能上與構(gòu)造函數(shù)/原型方式等價(jià)。可以采用這兩種方式中的任何一種。不過(guò)不要單獨(dú)使用經(jīng)典的構(gòu)造函數(shù)或原型方式,因?yàn)檫@樣會(huì)給代碼引入問(wèn)題。
復(fù)制代碼 代碼如下:

//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();

相關(guān)文章

最新評(píng)論