JavaScript物件導向程式設計(8): 優雅的封裝還是執行的效率?

來源:互聯網
上載者:User

 本部落格轉載於:http://devbean.javaeye.com/blog/412296

優雅的封裝還是執行的效率?這是一個悖論。

優雅封裝的程式看起來是那麼的美妙:每個屬性被隱藏在對象之後,你所能看到的就是這個對象讓

你看到的,至於它到底是怎麼操作的,這個不需要你操心。

執行的效率就是另外一回事。就像是C語言和物件導向的C++之間的差別:C++很優雅,但是執行效

率,無論是編譯後的二進位代碼還是運行期的記憶體的佔用,都要比簡單的C語言多出一截來。

這個問題在指令碼語言中顯得更加重要,因為JavaScript根本就是一種解釋語言,解釋語言的執行效

率要比編譯語言低很多。

1. 優雅的封裝

我們先來看看變數封裝。這裡的變數不僅僅是屬性,也包括函數。

前面已經說過,JavaScript中並沒有類這個概念,是我們利用變數範圍和閉包“巧妙的類比”出

來的,這是一種優雅的實現。還是溫故一下以前的代碼:

Js代碼

function Person() {<br /> var id;<br /> var showId = function() {<br /> alert("My id is " + id);<br /> }<br /> this.getId = function() {<br /> return id;<br /> }<br /> this.setId = function(newId) {<br /> id = newId;<br /> }<br />}<br />var p = new Person();<br />p.setId(1000);<br />alert(p.id); // undefined<br />// p.showId(); error: function not defined<br />var p2 = new Person();<br />alert(p.getId == p2.getId); // false

我們很優雅的實現了私人變數——儘管是投機取巧的實現的。但是,這段代碼又有什麼問題呢?為

什麼兩個對象的函數是不同的呢?

想一下,我們使用變數的範圍類比出私人變數,用閉包類比出公有變數,那麼,也就是說,實際

上每個建立的對象都會有一個相同的代碼的拷貝!不僅僅是那個id,就連那些showId、getId 等函

數也會建立多次。注意,考慮到JavaScript函數就是對象,就不會感到那麼奇怪了。但是毫無疑問

,這是一種浪費:每個變數所不同的只是自己的資料域,函數代碼都是相同的,因為我們進行的是

同一種操作。其他語言一般不會遇到這種問題,因為那些語言的函數和對象的概念是不同的,像

Java,每個對象的方法其實指向了同一份代碼的拷貝,而不是每個對象都會有自己的代碼拷貝。

2. 去看效率

那種封裝雖然優雅,但是很浪費。好在JavaScript是一種靈活的語言,於是,我們馬上想到,把這

些函數的指標指向另外的一個函數不就可以了嗎?

Js代碼

function show() {<br /> alert("I'm a person.");<br />}<br />function Person() {<br /> this.show = show;<br />}<br />var p1 = new Person();<br />var p2 = new Person();<br />alert(p1.show == p2.show); // true

這個辦法不錯,解決了我們以前的那個問題:不同的對象共用了一份代碼。但是這種實現雖然有了

效率,可是卻太不優雅了——如果我有很多類,那麼豈不是有很多全域函數?

好在JavaScript中還有一個機制:prototype。還記得這個prototype嗎?每個對象都維護著一個

prototype屬性,這些對象的prototype屬性是共用的。那麼,我們就可以把函數的定義放到

prototype裡面,於是,不同的對象不就共用了一份代碼拷貝嗎?事實確實如此:

Js代碼 

function Person() {<br />}<br />Person.prototype.show = function() {<br /> alert("I'm a person.");<br />}<br />var p1 = new Person();<br />var p2 = new Person();<br />alert(p1.show == p2.show); // true

不過,這種分開定義看上去很彆扭,那麼好,為什麼不把函數定義也寫到類定義裡面呢?

Js代碼

function Person() {<br /> Person.prototype.show = function() {<br /> alert("I'm a person.");<br /> }<br />}<br />var p1 = new Person();<br />var p2 = new Person();<br />alert(p1.show == p2.show); // true  

實際上這種寫法和上面一種沒有什麼不同:唯一的區別就是代碼位置不同。這隻是一個“看上去很甜”的文法糖,並沒有實質性差別。

最初,微軟的.Net AJAX架構使用前面的機制類比了私人變數和函數,這種寫法和C#很相像,十分的優雅。但是,處於效率的緣故,微軟後來把它改成了這種原型的定義方式。雖然這種方式不那麼優雅,但是很有效率。

在JavaScript中,這種封裝的優雅和執行的效率之間的矛盾一直存在。現在我們最好的解決方案就是把資料定義在類裡面,函數定義在類的prototype屬性裡面。

 

 

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.