JavaScript定義類(lèi)的幾種方式總結(jié)
提起面向?qū)ο笪覀兙湍芟氲筋?lèi),對(duì)象,封裝,繼承,多態(tài)。在《javaScript高級(jí)程序設(shè)計(jì)》(人民郵電出版社,曹力、張欣譯。英文名字是:Professional JavaScript for Web Developers)這本書(shū)中描述的還算比較詳細(xì)。我們看看JavaScript中定義類(lèi)的各種方法。
1.工廠方式
javaScript中創(chuàng)建自己的類(lèi)和對(duì)象,我們應(yīng)該是必須掌握的,我們都知道javaScript中對(duì)象的屬性可以在對(duì)象創(chuàng)建后動(dò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對(duì)象,但是我們創(chuàng)就是想創(chuàng)建多個(gè)Car實(shí)例。我們可以使用一個(gè)函數(shù)來(lái)封裝上面的代碼來(lái)實(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>
順便說(shuō)一下,javaScript對(duì)象默認(rèn)成員屬性都是public 的。這種方式我們稱(chēng)為工廠方式,我們創(chuàng)造了能創(chuàng)建并返回特定類(lèi)型的對(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ù)的形式定義類(lèi)。
2.構(gòu)造函數(shù)
這種方式看起來(lái)有點(diǎn)象工廠函數(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>
看起來(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ú)立,我們定義類(lèi)的目的就是為了共享方法以及數(shù)據(jù),但是car1對(duì)象與car2對(duì)象都是各自獨(dú)立的屬性與函數(shù),最起碼我們應(yīng)該共享方法。這就是原形方式的優(yōu)勢(shì)所在。
3.原型方式
利用對(duì)象的prototype屬性,可把它看出創(chuàng)建新對(duì)象所依賴的原型。方法如下:
<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ù)和原型方式,定義類(lèi)就非常方便。
<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ō),這種方式總有一些別扭??偢杏X(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é)不那么和諧。畢竟,定義類(lèi)時(shí),大多數(shù)面向?qū)ο笳Z(yǔ)言都對(duì)屬性和方法進(jìn)行了視覺(jué)上的封裝。考慮下面的C#類(lèi):
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類(lèi)的所有屬性和方法,因此看見(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類(lèi):
<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ǔ)言中的類(lèi)定義了。
6 混合工廠方式
這種方式通常是在不能應(yīng)用前一種方式時(shí)的變通方法。它的目的是創(chuàng)建假構(gòu)造函數(shù),只返回另一種對(duì)象的新實(shí)例。這段代碼看來(lái)與工廠函數(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運(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)題。
//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();
- JS定義類(lèi)的六種方式詳解
- JavaScript定義類(lèi)或函數(shù)的幾種方式小結(jié)
- 關(guān)于JavaScript定義類(lèi)和對(duì)象的幾種方式
- Javascript定義類(lèi)(class)的三種方法詳解
- Javascript 自定義類(lèi)型方法小結(jié)
- javascript面向?qū)ο笾?定義類(lèi)
- javascript來(lái)定義類(lèi)的規(guī)范小結(jié)
- ES6新特性之類(lèi)(Class)和繼承(Extends)相關(guān)概念與用法分析
- ES6中class類(lèi)用法實(shí)例淺析
- 老生常談ES6中的類(lèi)
- js定義類(lèi)的方法示例【ES5與ES6】
相關(guān)文章
JavaScript實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)飄落的雪花
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)動(dòng)態(tài)網(wǎng)頁(yè)飄落的雪花,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
前端音頻可視化Web?Audio實(shí)現(xiàn)示例詳解
這篇文章主要為大家介紹了前端音頻可視化Web?Audio實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
jQuery與JavaScript節(jié)點(diǎn)創(chuàng)建方法的對(duì)比
本文主要介紹jQuery與JavaScript節(jié)點(diǎn)的創(chuàng)建方法,以及他們的具體代碼實(shí)現(xiàn)方法,大家可以對(duì)比下他們之間的不同,希望對(duì)大家編寫(xiě)代碼有所幫助2016-11-11
js獲取當(dāng)前頁(yè)的URL與window.location.href簡(jiǎn)單方法
下面小編就為大家?guī)?lái)一篇js獲取當(dāng)前頁(yè)的URL與window.location.href簡(jiǎn)單方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02
js調(diào)用webservice中的方法實(shí)現(xiàn)思路及代碼
js調(diào)用webservice還算是一個(gè)比較實(shí)用的功能,本文提供了實(shí)現(xiàn)思路及代碼,感興趣的你可不要錯(cuò)過(guò)了哈,希望本文可以幫助到你啊2013-02-02
javascript計(jì)算當(dāng)月剩余天數(shù)(天數(shù)計(jì)算器)示例代碼
本文介紹了利用Javascript在網(wǎng)頁(yè)上計(jì)算當(dāng)前月份的剩余天數(shù)的方法,大家參考使用吧2014-01-01
JS中使用textPath實(shí)現(xiàn)線條上的文字
最近項(xiàng)目經(jīng)理交給我一下新項(xiàng)目,要實(shí)現(xiàn)關(guān)系圖,需要在線條上繪制文字。下面小編把使用textPath實(shí)現(xiàn)線條上的文字功能分享到腳本之家平臺(tái)供大家參考2017-12-12

