javascript物件導向之我解

來源:互聯網
上載者:User

今天要用js實現一些用戶端功能,考慮到商務邏輯,使用OO的開發方式會很方便,於是認真查看了相關的幾篇文章,有一些心得體會。

首先是定義類。js中定義類是使用function,執行個體化使用new操作符:

function class1() {
this.a = 'class1';
   this.m1 = function() {
    alert('class1.m1');
  }
}
class1.prototype.m2 = function() {
  alert('class1.m2');
}
var c1 = new class1();

在js中,Function和Object是兩個最基礎的類,js中的任何對象、執行個體、函數都同時是Function和Object的執行個體,這可以用instanceof來驗證,這一點有特殊的作用,後面的一些魔法全靠這一點支撐。

function有兩種用法,一種如上,是常用的形式;另一種是運行時動態建立,如

var add = new Function("x", "y", "return (x+y)");

建立的結果是一個Function對象。這可以解釋我之前看到的“奇怪”的用法。如上,this.m1 = function() {...}的用法中,實際上後面的function句自動產生了一個匿名的function對象,然後賦值給m1屬性,隨即class1就具有了m1方法。之後又用class1.prototype.m2 = function(){...}句定義了m2方法,實際上也是得到了匿名的function對象,然後賦值給m2屬性。當然,這兩種定義方法的形式是由區別的,後面會講到。既然得到的是一個對象,可以使用變數指代,當然就可以作為函數調用的參數了,也就可以輕鬆而自然的實現函數回調了。這比C#之類的語言實現回調更方便自然。

這裡再多囉嗦一句,js類在定義的時候可以定義屬性,如樣本中的a屬性。除此之外,執行個體的屬性是可以動態添加的。如果使用c1.b = 'b',則c1自動具有了屬性b。這種動態添加的屬性是不會擴散到其他執行個體的,即如果有另一個執行個體c2,則c2仍然只有屬性a而無屬性b。

如上樣本,任何類(class1)的函數有兩種實現方式,一種的內聯的方式,即在定義function的時候,將方法寫在body中;另一種是使用prototype,可以在任何地方定義。對於類的執行個體(class1的執行個體c1),同時擁有這兩種方式定義的方法。因為內聯定義的優先順序高,在執行個體調用方法時,首先尋找內聯定義,然後轉到prototype的定義中尋找。因此,prototype定義的方法會被內聯定義覆蓋掉。如果真的發生了方法覆蓋,要想使用prototype定義的方法,至少有兩種方法(以下假設class1中使用同時使用了上述兩種形式定義了方法m1)。

第一種是使用delete,首先delete掉m1方法,根據優先順序,自然delete掉的是內聯的m1方法。什麼,不明白為什麼還能delete掉方法?首先。js是動態語言;其次,記住方法也只是一個function執行個體,在class1中只是一個特殊屬性而已。

var c1 = new class1();
delete c1.m1; //去掉內聯的m1方法
c1.m1(); //調用prototype的m1方法

第二種是使用apply方法。至於apply的使用方法,可以查看js手冊。

var c1 = new class1();
class1.prototype.m.apply(c1); //使用prototype中定義的m方法代替c1的m方法

用new執行個體化的對象仍然同時是Function對象和Object對象,包括這兩者的所有執行個體屬性和方法。這裡不是很好理解,想想看,我們定義的類同時是Function對象和Object對象的執行個體,然後執行個體化後,執行個體也同時是Function對象和Object對象的執行個體,有沒有一點像父親和兒子的爸爸是同一個人?呵呵,有點噁心了,還希望高手出來詳細剖析一下Function對象和Object對象以及js裡面的類型關係。

這裡把js和ruby做個比較。js和ruby都有一個預設的全域對象,js中是Global對象,所用定義的全域變數和函數都是Global的成員。從這一點看,js也有一點oo的感覺(至少是形式上):-)。ruby中,同時存在class變數和執行個體變數,js也是。這種設計是指令碼語言的優勢,可以在運行時隨時改變class的定義,非常靈活和強大。同時兩種指令碼中的所有類型都不是封閉的,而是開放的,使用者可以給語言內建的所有類型添加額外的屬性和方法。

另外閑扯一下有趣的話題:js的反射。js中任何對象(function和object)都可以使用如下方式遍曆所有成員:

var info = typeof(obj)+'\n';
for(p in obj) {
  info += p + '\n';
}
alert(info);

同樣使用反射,可以這樣調用方法和屬性:

alert(c1['a']);
c1['m1']();

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.