javascript 的面向?qū)ο筇匦詤⒖?/h1>
更新時(shí)間:2007年01月10日 00:00:00 作者:
javascript 的面向?qū)ο筇匦詤⒖肌?
這是我學(xué)習(xí)javascript中面向?qū)ο筇匦缘囊稽c(diǎn)總結(jié)。希望對(duì)具有其他語(yǔ)言的面向?qū)ο笤O(shè)計(jì)經(jīng)驗(yàn)的朋友理解javascript的OO有所幫助。我具有c++,java和python的面向?qū)ο笤O(shè)計(jì)的經(jīng)驗(yàn)。
總的感受, javascript作為一種弱類(lèi)型的動(dòng)態(tài)語(yǔ)言,語(yǔ)法解決于java,但其面向?qū)ο蟮姆绞礁蚿ython相識(shí)。
1 面向?qū)ο蟮奶匦?/STRONG>
類(lèi),成員變量,成員函數(shù),類(lèi)變量,類(lèi)方法,繼承,多態(tài)
1) 類(lèi)
類(lèi)的定義:function Circle(r) { this.r = r; }
類(lèi)的實(shí)例化: c = Circle(3);
2)成員變量
成員變量在初始化函數(shù)里申明:this.r = r;
注意,在對(duì)象生成后,你也可以給它附上成員變量,比如c.name="my circle",
但是除非特別的需要,我強(qiáng)烈建議你不要這樣做。也就是所有的成員都應(yīng)在初始化函數(shù)里聲明。我認(rèn)為這是一種好的style。
這一點(diǎn)和python很相識(shí)。
3)成員函數(shù)
成員函數(shù)的標(biāo)準(zhǔn)形式是這樣的:
Cricle.prototype.area = function() { return 3.14 * this.r * this.r; }
這和java或python或c++都大不一樣。但為了幫助理解,你可以把prototype看作基類(lèi)。
prototype里面的變量或方法,是所有對(duì)象共享的。
比如,c.area()調(diào)用最終就會(huì)讓解釋器調(diào)用到Circle.prototype.area().
相比于java和c++,javascript具有他們都沒(méi)有的一個(gè)語(yǔ)義,也就是你可以在prototype里定義變量。定義在prototype里的變量可以被所有的實(shí)例共享量。所以一般它應(yīng)該是一個(gè)常數(shù),比如:Circle.prototype.PI = 3.14.
顯然,prototype里的變量和方法都應(yīng)該是不變的。每一個(gè)對(duì)象實(shí)例都不應(yīng)該取修改prototype中的內(nèi)容。雖然語(yǔ)言允許你可以這樣做,但這樣做沒(méi)有任何意義,也違反了面向?qū)ο蟮恼Z(yǔ)義(想想,java會(huì)讓你動(dòng)態(tài)修改一個(gè)類(lèi)的方法嗎)。
當(dāng)然,對(duì)于多態(tài)是另外一回事,在后面詳述。
而且,我建議所有的成員函數(shù)都在緊接類(lèi)定義的地方定義。而不應(yīng)該在代碼運(yùn)行的某個(gè)地方對(duì)一個(gè)對(duì)象實(shí)例增加/修改成員函數(shù)。這樣的結(jié)果是javascript的類(lèi)定義盡量向java看齊。使得代碼更清晰。
4)類(lèi)變量
類(lèi)變量是屬于一個(gè)類(lèi)的變量。就像java里用static修飾的變量。因?yàn)樗鼘儆陬?lèi),所以它也應(yīng)該是一個(gè)常量。實(shí)例不應(yīng)該去修改它,雖然你可以(java里可以用final修飾,使得類(lèi)變量一旦定義,就不能修改)。
這里可以看到,類(lèi)變量和prototype里定義的變量的功能是相似的。確實(shí)如此,他們的目的都是一樣的。但他們的訪問(wèn)方式
不一樣。比如:
Circle.prototype.PI = 3.14;
Circle.PI = 3.14;
//用prototype里的變量
Circle.prototype.area1 = function() { return this.PI * this.r * this.r; }
//用類(lèi)變量
Circle.prototype.area2 = function() { return Circle.PI * this.r * this.r; }
5)類(lèi)方法
這個(gè)概念應(yīng)該很簡(jiǎn)單。注意類(lèi)方法里絕對(duì)不要用this關(guān)鍵字,和java完全一樣。
Circle.max = function(a, b) { return a.r > b.r ? a : b; }
theMax = Circle(new Circle(1), new Circle(4));
6)繼承
子類(lèi)繼承父類(lèi),那么 “子類(lèi)實(shí)例” 具有和 “父類(lèi)實(shí)例” 完全一樣的行為。javascript是這樣實(shí)現(xiàn)的。
function SubCircle(x, y, r) { this.x = x; this.y = y; this.r =r; }
SubCircle.prototype = new Circle(0);
記得前面說(shuō)的嗎?可以把prototype看作一個(gè)基類(lèi)。這里,prototype確確實(shí)實(shí)是一個(gè)基類(lèi)。它是如何實(shí)現(xiàn)的呢?
舉例如下:sc = SubCirlce(1,1,3); sc.area();
調(diào)用的傳遞: sc.area()->sc.prototype.area()->Circle(0).area()->Circle.prototype.area().看來(lái)是不是很奇妙呢。
通過(guò)這種方式,javascript實(shí)現(xiàn)了繼承。
7)多態(tài)
多態(tài)是子類(lèi)會(huì)定義和父類(lèi)具有相同signature的方法。假設(shè)在SubCircle所在的空間PI=100,而面積公式也變?yōu)?nbsp;PI*R*R*R。
SubCircle.prototype.PI = 100
SubCircle.prototype.area = function() { return this.PI*this.r*this.r*this.r; }
Sc.area() 這樣的操作可以認(rèn)為是:
Sc.PI->sc.prototype.PI->Cricle(0).PI = 100
Sc.area()->sc.prototype.area()->Circle(0).area.
這個(gè)時(shí)候,調(diào)用過(guò)程是這樣的
sc.area()->sc.prototype.area(),在這里解釋器發(fā)現(xiàn)了area這個(gè)方法,于是它就調(diào)用此方法。
而Cricle.prototype.area就永遠(yuǎn)也不會(huì)被調(diào)用。PI的調(diào)用也是如此。
那么子類(lèi)如何想調(diào)用父類(lèi)的方法應(yīng)怎么辦呢?好像沒(méi)有什么辦法哦,誰(shuí)知道可以告訴我。但面向?qū)ο蟮睦碚摳嬖V我們,繼承主要是提供接口而不是代碼復(fù)用,所以還是少有這樣的念頭為好 :)。
下面是一個(gè)例子程序。包含上面的所有的概念。
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
您可能感興趣的文章:- Javascript基于對(duì)象三大特性(封裝性、繼承性、多態(tài)性)
- JavaScript實(shí)現(xiàn)多態(tài)和繼承的封裝操作示例
- JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
- JavaScript 繼承 封裝 多態(tài)實(shí)現(xiàn)及原理詳解
- Javascript 面向?qū)ο筇匦?/a>
- 利用javascript的面向?qū)ο蟮奶匦詫?shí)現(xiàn)限制試用期
- javascript面向?qū)ο蟪绦蛟O(shè)計(jì)高級(jí)特性經(jīng)典教程(值得收藏)
- js面向?qū)ο笾小⑺接?、靜態(tài)屬性和方法詳解
- js面向?qū)ο笾R?jiàn)創(chuàng)建對(duì)象的幾種方式(工廠模式、構(gòu)造函數(shù)模式、原型模式)
- javascript 面向?qū)ο缶幊袒A(chǔ) 多態(tài)
- JavaScript面向?qū)ο笾甈rototypes和繼承
- JavaScript面向?qū)ο笕齻€(gè)基本特征實(shí)例詳解【封裝、繼承與多態(tài)】
相關(guān)文章
javascript 的面向?qū)ο筇匦詤⒖肌?
這是我學(xué)習(xí)javascript中面向?qū)ο筇匦缘囊稽c(diǎn)總結(jié)。希望對(duì)具有其他語(yǔ)言的面向?qū)ο笤O(shè)計(jì)經(jīng)驗(yàn)的朋友理解javascript的OO有所幫助。我具有c++,java和python的面向?qū)ο笤O(shè)計(jì)的經(jīng)驗(yàn)。
總的感受, javascript作為一種弱類(lèi)型的動(dòng)態(tài)語(yǔ)言,語(yǔ)法解決于java,但其面向?qū)ο蟮姆绞礁蚿ython相識(shí)。
1 面向?qū)ο蟮奶匦?/STRONG>
類(lèi),成員變量,成員函數(shù),類(lèi)變量,類(lèi)方法,繼承,多態(tài)
1) 類(lèi)
類(lèi)的定義:function Circle(r) { this.r = r; }
類(lèi)的實(shí)例化: c = Circle(3);
2)成員變量
成員變量在初始化函數(shù)里申明:this.r = r;
注意,在對(duì)象生成后,你也可以給它附上成員變量,比如c.name="my circle",
但是除非特別的需要,我強(qiáng)烈建議你不要這樣做。也就是所有的成員都應(yīng)在初始化函數(shù)里聲明。我認(rèn)為這是一種好的style。
這一點(diǎn)和python很相識(shí)。
3)成員函數(shù)
成員函數(shù)的標(biāo)準(zhǔn)形式是這樣的:
Cricle.prototype.area = function() { return 3.14 * this.r * this.r; }
這和java或python或c++都大不一樣。但為了幫助理解,你可以把prototype看作基類(lèi)。
prototype里面的變量或方法,是所有對(duì)象共享的。
比如,c.area()調(diào)用最終就會(huì)讓解釋器調(diào)用到Circle.prototype.area().
相比于java和c++,javascript具有他們都沒(méi)有的一個(gè)語(yǔ)義,也就是你可以在prototype里定義變量。定義在prototype里的變量可以被所有的實(shí)例共享量。所以一般它應(yīng)該是一個(gè)常數(shù),比如:Circle.prototype.PI = 3.14.
顯然,prototype里的變量和方法都應(yīng)該是不變的。每一個(gè)對(duì)象實(shí)例都不應(yīng)該取修改prototype中的內(nèi)容。雖然語(yǔ)言允許你可以這樣做,但這樣做沒(méi)有任何意義,也違反了面向?qū)ο蟮恼Z(yǔ)義(想想,java會(huì)讓你動(dòng)態(tài)修改一個(gè)類(lèi)的方法嗎)。
當(dāng)然,對(duì)于多態(tài)是另外一回事,在后面詳述。
而且,我建議所有的成員函數(shù)都在緊接類(lèi)定義的地方定義。而不應(yīng)該在代碼運(yùn)行的某個(gè)地方對(duì)一個(gè)對(duì)象實(shí)例增加/修改成員函數(shù)。這樣的結(jié)果是javascript的類(lèi)定義盡量向java看齊。使得代碼更清晰。
4)類(lèi)變量
類(lèi)變量是屬于一個(gè)類(lèi)的變量。就像java里用static修飾的變量。因?yàn)樗鼘儆陬?lèi),所以它也應(yīng)該是一個(gè)常量。實(shí)例不應(yīng)該去修改它,雖然你可以(java里可以用final修飾,使得類(lèi)變量一旦定義,就不能修改)。
這里可以看到,類(lèi)變量和prototype里定義的變量的功能是相似的。確實(shí)如此,他們的目的都是一樣的。但他們的訪問(wèn)方式
不一樣。比如:
Circle.prototype.PI = 3.14;
Circle.PI = 3.14;
//用prototype里的變量
Circle.prototype.area1 = function() { return this.PI * this.r * this.r; }
//用類(lèi)變量
Circle.prototype.area2 = function() { return Circle.PI * this.r * this.r; }
5)類(lèi)方法
這個(gè)概念應(yīng)該很簡(jiǎn)單。注意類(lèi)方法里絕對(duì)不要用this關(guān)鍵字,和java完全一樣。
Circle.max = function(a, b) { return a.r > b.r ? a : b; }
theMax = Circle(new Circle(1), new Circle(4));
6)繼承
子類(lèi)繼承父類(lèi),那么 “子類(lèi)實(shí)例” 具有和 “父類(lèi)實(shí)例” 完全一樣的行為。javascript是這樣實(shí)現(xiàn)的。
function SubCircle(x, y, r) { this.x = x; this.y = y; this.r =r; }
SubCircle.prototype = new Circle(0);
記得前面說(shuō)的嗎?可以把prototype看作一個(gè)基類(lèi)。這里,prototype確確實(shí)實(shí)是一個(gè)基類(lèi)。它是如何實(shí)現(xiàn)的呢?
舉例如下:sc = SubCirlce(1,1,3); sc.area();
調(diào)用的傳遞: sc.area()->sc.prototype.area()->Circle(0).area()->Circle.prototype.area().看來(lái)是不是很奇妙呢。
通過(guò)這種方式,javascript實(shí)現(xiàn)了繼承。
7)多態(tài)
多態(tài)是子類(lèi)會(huì)定義和父類(lèi)具有相同signature的方法。假設(shè)在SubCircle所在的空間PI=100,而面積公式也變?yōu)?nbsp;PI*R*R*R。
SubCircle.prototype.PI = 100
SubCircle.prototype.area = function() { return this.PI*this.r*this.r*this.r; }
Sc.area() 這樣的操作可以認(rèn)為是:
Sc.PI->sc.prototype.PI->Cricle(0).PI = 100
Sc.area()->sc.prototype.area()->Circle(0).area.
這個(gè)時(shí)候,調(diào)用過(guò)程是這樣的
sc.area()->sc.prototype.area(),在這里解釋器發(fā)現(xiàn)了area這個(gè)方法,于是它就調(diào)用此方法。
而Cricle.prototype.area就永遠(yuǎn)也不會(huì)被調(diào)用。PI的調(diào)用也是如此。
那么子類(lèi)如何想調(diào)用父類(lèi)的方法應(yīng)怎么辦呢?好像沒(méi)有什么辦法哦,誰(shuí)知道可以告訴我。但面向?qū)ο蟮睦碚摳嬖V我們,繼承主要是提供接口而不是代碼復(fù)用,所以還是少有這樣的念頭為好 :)。
下面是一個(gè)例子程序。包含上面的所有的概念。
[Ctrl+A 全選 注:引入外部Js需再刷新一下頁(yè)面才能執(zhí)行]
- Javascript基于對(duì)象三大特性(封裝性、繼承性、多態(tài)性)
- JavaScript實(shí)現(xiàn)多態(tài)和繼承的封裝操作示例
- JavaScript使用prototype原型實(shí)現(xiàn)的封裝繼承多態(tài)示例
- JavaScript 繼承 封裝 多態(tài)實(shí)現(xiàn)及原理詳解
- Javascript 面向?qū)ο筇匦?/a>
- 利用javascript的面向?qū)ο蟮奶匦詫?shí)現(xiàn)限制試用期
- javascript面向?qū)ο蟪绦蛟O(shè)計(jì)高級(jí)特性經(jīng)典教程(值得收藏)
- js面向?qū)ο笾小⑺接?、靜態(tài)屬性和方法詳解
- js面向?qū)ο笾R?jiàn)創(chuàng)建對(duì)象的幾種方式(工廠模式、構(gòu)造函數(shù)模式、原型模式)
- javascript 面向?qū)ο缶幊袒A(chǔ) 多態(tài)
- JavaScript面向?qū)ο笾甈rototypes和繼承
- JavaScript面向?qū)ο笕齻€(gè)基本特征實(shí)例詳解【封裝、繼承與多態(tài)】
相關(guān)文章
設(shè)計(jì)模式中的組合模式在JavaScript程序構(gòu)建中的使用
常用的Javascript數(shù)據(jù)驗(yàn)證插件
Google Dart編程語(yǔ)法和基本類(lèi)型學(xué)習(xí)教程
javascript實(shí)現(xiàn)dom元素可拖動(dòng)

