weidagang2046的專欄

          物格而后知致
          隨筆 - 8, 文章 - 409, 評(píng)論 - 101, 引用 - 0
          數(shù)據(jù)加載中……

          javascript 的面向?qū)ο筇匦詤⒖?/a>

          最近在看用javascript+css實(shí)現(xiàn)rich client。javascript 也是一個(gè)蠻有意思的語(yǔ)言。特別是其面向?qū)ο蟮膶?shí)現(xiàn)和其他“標(biāo)準(zhǔn)”的OO launguage有很大的不同。但是,都是動(dòng)態(tài)語(yǔ)言,我還是覺得它比起python語(yǔ)法和庫(kù)都差得太遠(yuǎn)。可是沒有explorer支持python開發(fā)啊。。。:(


          這是我學(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作為一種弱類型的動(dòng)態(tài)語(yǔ)言,語(yǔ)法接近于java,但其面向?qū)ο蟮姆绞礁蚿ython相識(shí)。

          1 面向?qū)ο蟮奶匦?/strong>


          類,成員變量,成員函數(shù),類變量,類方法,繼承,多態(tài)

          1) 類


          類的定義:function Circle(r) { this.r = r; }


          類的實(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看作基類。


          prototype里面的變量或方法,是所有對(duì)象共享的。


          比如,c.area()調(diào)用最終就會(huì)讓解釋器調(diào)用到Circle.prototype.area().

          相比于java和c++,javascript具有他們都沒有的一個(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ǔ)言允許你可以這樣做,但這樣做沒有任何意義,也違反了面向?qū)ο蟮恼Z(yǔ)義(想想,java會(huì)讓你動(dòng)態(tài)修改一個(gè)類的方法嗎)。


          當(dāng)然,對(duì)于多態(tài)是另外一回事,在后面詳述。

          而且,我建議所有的成員函數(shù)都在緊接類定義的地方定義。而不應(yīng)該在代碼運(yùn)行的某個(gè)地方對(duì)一個(gè)對(duì)象實(shí)例增加/修改成員函數(shù)。這樣的結(jié)果是javascript的類定義盡量向java看齊。使得代碼更清晰。

          4)類變量


          類變量是屬于一個(gè)類的變量。就像java里用static修飾的變量。因?yàn)樗鼘儆陬悾运矐?yīng)該是一個(gè)常量。實(shí)例不應(yīng)該去修改它,雖然你可以(java里可以用final修飾,使得類變量一旦定義,就不能修改)。這里可以看到,類變量和prototype里定義的變量的功能是相似的。確實(shí)如此,他們的目的都是一樣的。但他們的訪問方式


          不一樣。比如:


          Circle.prototype.PI = 3.14;


          Circle.PI = 3.14;


          //用prototype里的變量


          Circle.prototype.area1 = function() { return this.PI * this.r * this.r; }


          //用類變量


          Circle.prototype.area2 = function() { return Circle.PI * this.r * this.r; }

          5)類方法


          這個(gè)概念應(yīng)該很簡(jiǎn)單。注意類方法里絕對(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)繼承


          子類繼承父類,那么 “子類實(shí)例” 具有和 “父類實(shí)例” 完全一樣的行為。javascript是這樣實(shí)現(xiàn)的。


          function SubCircle(x, y, r) {
          ? this.x = x;
          ? this.y = y;
          ? this.r =r;
          }


          SubCircle.prototype = new Circle(0);
          記得前面說的嗎?可以把prototype看作一個(gè)基類。這里,prototype確確實(shí)實(shí)是一個(gè)基類。它是如何實(shí)現(xiàn)的呢?


          舉例如下:
          sc = SubCirlce(1,1,3);
          sc.area();


          調(diào)用的傳遞:
          sc.area()->sc.prototype.area()->Circle(0).area()->Circle.prototype.area().
          看來是不是很奇妙呢。


          通過這種方式,javascript實(shí)現(xiàn)了繼承。

          7)多態(tài)


          多態(tài)是子類會(huì)定義和父類具有相同signature的方法。假設(shè)在SubCircle所在的空間PI=100,而面積公式也變?yōu)?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)用過程是這樣的


          sc.area()->sc.prototype.area(),在這里解釋器發(fā)現(xiàn)了area這個(gè)方法,于是它就調(diào)用此方法。


          而Cricle.prototype.area就永遠(yuǎn)也不會(huì)被調(diào)用。PI的調(diào)用也是如此。那么子類如何想調(diào)用父類的方法應(yīng)怎么辦呢?好像沒有什么辦法哦,誰(shuí)知道可以告訴我。但面向?qū)ο蟮睦碚摳嬖V我們,繼承主要是提供接口而不是代碼復(fù)用,所以還是少有這樣的念頭為好 :)。


          下面是一個(gè)例子程序。包含上面的所有的概念。
          例子
          ///////////define: Cricle//////////////////
          function Circle(r) {
          this.r = r;
          }
          Circle.PI = 3.14;
          Circle.prototype.PI = 3.14;
          Circle.prototype.area = function() { return Circle.PI*this.r*this.r; }
          Circle.prototype.area2 = function() { return this.PI*this.r*this.r; }



          //// test
          c = new Circle(3);
          //alert("area1 :"+c.area());
          //alert("area2 :"+c.area2());

          Circle.max = function(a, b) { return a.r>b.r ? a.r : b.r; }
          //alert("max is "+Circle.max(new Circle(1), new Circle(3)));

          c1 = new Circle(1);
          c2 = new Circle(1);
          c2.PI = 100;//Circle.prototype.PI=100;

          //alert("c1.area1 "+c1.area());
          //alert("c1.area2 "+c1.area2());
          //alert("c2.area1 "+c2.area());
          //alert("c2.area2 "+c2.area2());


          ////////////////////////define: SubCircle //////////////////
          function SubCircle(x, y, r) {
          this.x = x;
          this.y = y;
          this.r = r;
          }
          SubCircle.prototype = new Circle(0);
          SubCircle.prototype.PI = 100;
          SubCircle.prototype.move2 = function(x, y) { this.x = x; this.y = y;}
          SubCircle.prototype.area = function() { return this.PI*this.r*this.r*this.r; }

          //// test
          sc = new SubCircle(0,0,2);

          alert(sc.area());

          from:
          http://www.klstudio.com/post/52.html

          posted on 2006-12-08 14:00 weidagang2046 閱讀(245) 評(píng)論(0)  編輯  收藏 所屬分類: Javascript

          主站蜘蛛池模板: 观塘区| 澎湖县| 山阴县| 襄汾县| 阿拉尔市| 宜黄县| 赤壁市| 马鞍山市| 金塔县| 凉山| 衡阳市| 郓城县| 台安县| 永德县| 玉环县| 江阴市| 蒙山县| 平定县| 石狮市| 克拉玛依市| 临江市| 兴山县| 颍上县| 福鼎市| 姜堰市| 神农架林区| 安远县| 陆川县| 青岛市| 洛宁县| 汝阳县| 呼和浩特市| 通许县| 繁峙县| 丰原市| 潞西市| 雅安市| 图们市| 托克逊县| 浦县| 哈巴河县|