天天看點

JavaScript的面向對象設計

轉載請注明出處:http://blog.csdn.net/horkychen

依據W3C School的定義,Javascript是面向對象的語言, 雖然沒有類(class),但到處是對象. 可以了解隻有定義而沒有聲明, 直接用就行. 其中的每個對象都可以了解為一組Key-Value的組合.

附上W3C School的說明:

 面向對象語言的要求

  一種面向對象語言需要向開發者提供四種基本能力:

封裝 -把相關的資訊(無論資料或方法)存儲在對象中的能力

聚集 -把一個對象存儲在另一個對象内的能力

繼承 -由另一個類(或多個類)得來類的屬性和方法的能力

多态 -編寫能以多種方法運作的函數或方法的能力

ECMAScript支援這些要求,是以可被是看做面向對象的。

下面就是一比較規矩的對象定義 (以下的例子參考了<<JavaScript進階程式設計>>):

 var person = new Object();

 person.name = "Horky";

 person.age = 40;

 person.job = "Software Engineer";

 person.sayName = function(){

document.write(this.name);

}

調用方式:

 person.sayName();

  document.write("<p /> Age: ");

  document.write(person.age);

  document.write("<p /> Job: ");

  document.write(person["job"]);

嗯,是的,所有屬性都是public的,而且有兩種不同的屬性通路方式. (關于通路性的限定可以由屬性(property)的特性(attribute)來設定.)

再一種是比較随意而且切中Key-Value的定義方式, 但是老版本的浏覽器可不見得支援:

var person = {

 name: "Horky",

 age: 40,

 job: "Software Engineer",

 sayName: function(){

 }

};

因為Javascript的變量本質是松散類型,說白了就是無政府主義型. 是以并不需要一開始就給出完整定義,而是像下面這樣也是允許的 (展示需要,絕不推薦):

   var person = new Object();

   person.name = "Horky";

   person.sayName = function()

   {

       document.write(this.name);

    }

    person.sayName();

    person.age = 40;

    document.write("<p /> Age: ");

    document.write(person.age);

    person.job = "Software Engineer";

    document.write("<p /> Job: ");

    document.write(person["job"]);

也不是沒有限制. 如果第一句改為下面這樣可就不行了:

   var person;  或者 var person = "Undefined";

原因還是在Javascript中基本資料類型和引用類型還是泾渭分明的.

回顧一下前面所講的JavaScript擁有面向對象的特性,前面兩點不用多說, 引用類型就比較明顯具備, 第三點稍後再說. 關于多态, 其實真有點牽強, 個人覺得更像是C/C++中的可變參數的函數. 因為這裡的多态針對函數而言. 也就是一個函數的參數可以很随性, JavaScript也懶得限定,一切交給開發者吧.結果還整出一個多态來.

結合建構子舉個例子吧:

function Person(name, age, job)

{

this.name = "Mr Nobody!";

this.age = 0;

this.job = "Hard to say!";

switch(arguments.length)

case 3:

this.job = job;

case 2:

this.age = age;

case 1:

this.name = name;

break;

this.introduceSelf = function()

 {

 document.write("<p /> My name is: "+this.name);

 document.write("<p /> "+ this.age+" years old!");

 document.write("<p /> And, my job is : "+this.job);

var horky = new Person("Horky",40,"Software Engineer");

var arthas = new Person("Arthas",22);

var nobody = new Person();

這個函數Person()就是一個建構函數, 建立一個Person的對象并傳回. 依據傳入的不同參數執行不同的初始化,這也就是多态的一種展現了.

擴充一下,如果傳入的是對象,如何實作複制呢? 這就是原型式繼承的模式 (參<<JavaScript進階程式設計>> 6.3.4).

增加一個全局函數:

function object(o)

  function F() {};

  F.prototype = o;

  return new F();

然後試試以下兩個新的對象:

var horky_alias = object(horky);

var arthas_alias = object(horky, {name:{value:"Arthas"}}); 

第二個對象在複制horky時,順便将其中的名字也給改了. 

它可以工作的核心在F.prototype上. 因為這個特殊指針的存在,使得這一切成為可能.每個函數都有一個prototype,它是一個指向某個對象的指針, 而這個對象包含了所有執行個體可以共享的屬性和方法, 很像是享元的概念.

下面就說一下繼承. JavaScript中所講的繼承,說白了就是使子對象可以通路父對象. 是以有兩個重點: 子對象中需要有一個父對象的執行個體, 那就是prototype. 于是一個典型的子對象定義出來了:

function Boy(name, age, job)

this.sex = "Male";

this.prototype = new Person(name,age,job);

 this.prototype.introduceSelf();

 document.write("<p /> I am BOY!");

var boy = new Boy("A",3);

如果覺得使用prototype太過于底層,也有幾分hack的味道,也可以使用"借用構造函數"的方式來實作簡單一些繼承.  

繼續閱讀