JavaScript與對象

    剛接觸JavaScript時,很多書上都強調一個概念:JavaScript僅僅是基於對象(Object-Based)的語言。怎麼解釋這個“基於對象”,我理解爲是JavaScript對面向對象語言的基本特徵(自定義類,封裝,繼承,覆蓋,多態)支持不夠。JavaScript日常編程中很少去創建自己的類,語言本身提供了豐富的對象類型,並且自動創建了大量的對象供我們使用。但是Javascript也同樣提供一些面嚮對象語言(Object-Oriented)的特性,比如定義類,支持繼承等等,這些特性是平時不太用到的。下面先從不通角度對JavaScript對象的分下類別。

一,靜態對象和動態對象
  在Javascript編程時你會發現,很多對象是不用去new的,比String對象,Math對象。比如使用Math四捨五入,直接調用Math.round(),這看起來很像調用Java中類的靜態方法,但在JavaScript中這叫靜態對象,像是在玩感念,不知道內部實現有沒有什麼相似之處。動態對象上是需要new的,比如:new Date(),new Array();此類對象之所以要new,是因爲創建新的對象的狀態需要制定,即需要傳入參數。靜態對象基本要麼不需要參數,要麼不需要我們提供。根據我們自己的類創建的對象,也劃到動態對象裏吧。

二,內部對象,瀏覽器對象,DHTML對象,自定義對象
  JavaScript提供的內部對象多用於計算,有:String,Date,Math,Array...;瀏覽器對象由瀏覽器提供,通過這些對象可以操縱瀏覽器,JavaScript可以直接引用:window,document,history...;DHTML對象,簡單理解就是把HTML對象解析成DOM樹,通過DHTML對象可以動態操縱HTML,CSS元素:table,form,image...;自定義對象,作者自己根據自定義類創建的對象,一般很少用到。

  前面提到JavaScript稱不上是面向對象的語言,相對於Java這樣純面向對象的語言,她提供的面向對象編程(OOP)支持相對弱了許多,下面從面向對象的一些基本特徵入手與Java比較一番。
一,自定義類
  類是一種藍圖,對象是根據這個藍圖創建的“實物”,經典的比喻是圖紙和大廈。Java可以非常方便的自定義類,提供的支持包括:包,類的可見修飾(public,缺省),抽象類,final類,內部類,匿名類(內部類也可以是靜態的),類的域和方法,以及接口(需要注意的是接口不繼承Object,但她的實現類會繼承Object。虛擬機規範中指出,接口不會隱藏Object類的方法)等。JavaScript語言只提供簡單的自定義類(有些書中把這叫做自定義對象,是不準確的)的方法:
 function cat(name) {
 this.name = name;
 this.talk = function() {
    alert( this.name + " say meeow!" );
       }
 }

 cat1 = new cat("felix");
 cat1.talk();
  JavaScript裏,一般把類叫做對象的原型,也有叫構造器函數的,原型用fonction定義,它的屬性和方法在函數體裏用this來定義,並用new來實例對象。可能也支持內部類。看得出與Java相比,單薄了許多,但JavaScript有一個功能是Java沒有得,就是通過prototype屬性,在原型裏增加方法。
 cat.prototype.changeName = function(name) {
     this.name = name;
    }
 cat2 = new cat("pursur");
 cat2.changeName("Bill");
 cat2.talk();
  可以看出,新定義得對象中,增加了changeName()方法(不知道cat1中也增加了這個方法嗎?我猜應該也增加了,有空試試)。這個方法被所有的改原型得實例共享。prototype也可以對其他非自定義原型工作,比如
 String.prototype.half=function(){
     return --half String;
   }
  JavaScript管這叫用原型(prototype)重載JavaScript對象
二,封裝
  封裝,就好比機頂盒,把主要的部件都封裝在一個盒子裏面,對外暴露幾個輸入輸出接口。Java得封裝是限制了域和方法得可見範圍。這中封裝,不僅僅是利用域和方法的修飾符(public,private,protected,dufalt)來實現,通過多態,也可以屏蔽子類對象的方法。舉例如下:
 interface Teacher{
  void teach();
 }
 interface Playactor {
  void play();
 }
 class Liuyapeng implementTeacher, Playactor {
  public joke() {
  }
 }
 ...
 Liuyapeng liuyapeng = new Liuyapeng();
 Teacher teacher = new Liuyapeng();
 Playactor playactor = new Liuyapeng();
 ...
  這三個方法都是public修飾符,但teacher只能看到teach(),playactor只能看到play(),liuyapeng能看到三個方法。雖說Java中沒有多繼承,但一個類有多個角色,我管這叫由多角色引起的封裝。
  JavaScript中沒有修飾符,沒有多繼承,也沒有多角色。JavaScript原型的方法和屬性都是可見的。所以JavaScript其實沒有封裝,更像是把關聯的變量和方法打包在一起,然後用new來分配空間。當然想我們這樣深受面向對象思想“毒害”的一代Coder來說,看成簡單版本的有充分安全感的對象,更有符合思維習慣。
三,繼承
  Java中只有單繼承,但可有有多實現(多角色-我喜歡這麼叫)。Java的繼承還涉及到父類域和方法繼承後的可見性(注意,父類的域和方法都被繼承下來,只是有些在子類中是不能直接看到,可有用super.xxx來訪問。創建子類對象是,父類中那些不可見的域也是要分配空間的。)。JavaScript也支持繼承,但不涉及到可見性和多實現。一下是JavaScript關於繼承的一段引文:
In Java and C++, there is an explicit concept of the class hierarchy. i.e. Every class can have a super class from which it inherits properties and methods. Any class can be extended, or sub-classed so the resulting subclass can inherit its parent's behavior. As we have seen, javascript supports prototype inheritance instead of class based. It's possible for inheritance to happen other ways, however.

The following is an example of inheritance through functions.
 <script language="javascript" type="text/javascript">
     <!--
  // thanks to webreference
  function superClass() {
   this.supertest = superTest; //attach method superTest
  }

  function subClass() {
   this.inheritFrom = superClass;
   this.inheritFrom();
   this.subtest = subTest; //attach method subTest
  }

  function superTest() {
   return "superTest";
  }

  function subTest() {
   return "subTest";
  }

  var newClass = new subClass();

  alert(newClass.subtest()); // yields "subTest"
  alert(newClass.supertest()); // yields "superTest"

   -->
 </script>

四,覆蓋
  Java中覆蓋(OverWrite)和重載(OverLoad)是兩個不通的概念,覆蓋發生在子類和父類之間,並且方法名,參數列表和返回類型嚴格相同(在jdk1.5版本中子類方法的返回類型可以是父類方法返回類型的子類--待求證)。
  JavaScript中沒有覆蓋和重載的概念。
五,多態
  多態是個好東西,她能讓你的程序更智能。有了繼承和覆蓋纔會有多態,在Java中,多態有編譯時多態和運行時多態的區別,編譯時多態和方法的重載有關。運行時多態,包含兩個概念,一是:子類型對象和父類型兼容。二是:會優先查找對象中覆蓋的方法並執行,你提供的僅僅是引用變量的類型中的那個方法的簽名。累啦就不舉例子啦。
  JavaScript連覆蓋都沒有,就談不上多態啦。
  通過上述比較,很明顯看出JavaScript僅支持類(原型)和類(原型)的繼承。所以也談不上面向對象的語言。不過JavaScript依然是很成功的語言,使用她可以很輕鬆的左右瀏覽器的行爲,實現動態交互頁面,驗證表單數據數據。JavaScrit提供自定義類型的功能雖然相對較弱,但利用起來也還順手。下面蒐集一下JavaScript自定義對象方法和使用的技巧,和大家交流。

一,自定義對象的方法--摘至網絡
  1,用 new Object() 來創建對象
 在javascript裏有幾種創建對象的方法,在不同的場合可用不同的方法.最簡單的就是用 new 操作符,例如:
 <script language="javascript" type="text/javascript">
   <!--
  person = new Object()
  person.name = "Tim Scarfe"
  person.height = "6Ft"
  person.run = function() {
    this.state = "running"
    this.speed = "4ms^-1"
   }
   -->
 </script>
 我們在這個例子裏定義了person這個對象,然後加入了它的屬性和方法.在這個例子裏,自定義的方法裏有兩個屬性。
  2,用文字記號(Literal Notation)創建對象
 用文字記號也可以創建對象,但要javascript 1.2以上版本.它的創建形式是多樣的。
 <script language="javascript" type="text/javascript">
    <!--
  // Object Literals
  timObject = {
   property1 : "Hello",
   property2 : "MmmMMm",
   property3 : ["mmm", 2, 3, 6, "kkk"],
   method1 : function(){alert("Method had been called" + this.property1)}
  };
  timObject.method1();
  alert(timObject.property3[2]) // will yield 3

  // another example
  var circle = { x : 0, y : 0, radius: 2 }
  // nesting is no problem.
  var rectangle = {
   upperLeft : { x : 2, y : 2 },
   lowerRight : { x : 4, y : 4}
  }
  alert(rectangle.upperLeft.x) // will yield 2
      //-->
 </script>
 文字記號可是是數組,也可以是任意的javascript表達式或值。
  3,通過構造器函數創建對象並通過prototype修改y原型的方法和屬性--前面已經介紹。
  在僅僅定義單個對象是第一、二種方法更靈活,屬性太多的話,在定義一組有相同屬性和方法的對象時,第三鍾更有效。
二,使用技巧
  1,使用對象把一組相關的變量集中起來。
  2,使用for in和聯合數組遍歷屬性。
 <script language="javascript" type="text/javascript">
   <!--
  var testObj = {
  prop1 : "hello",
  prop2 : "hello2",
  prop3 : new Array("hello",1,2)
  };
  for(x in testObj) {
   alert( x + "-" + testObj[ x ] );
  }
   -->
 </script>
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章