AJAX中JavaScript類的三種成員/反射機制

導讀:
實現類的私有成員

  私有成員即在類的內部實現中可以共享的成員,不對外公開。JavaScript中並沒有特殊的機制來定義私有成員,但可以用一些技巧來實現這個功能。

  這個技巧主要是通過變量的作用域性質來實現的,在JavaScript中,一個函數內部定義的變量稱爲局部變量,該變量不能夠被此函數外的程序所訪問,卻可以被函數內部定義的嵌套函數所訪問。在實現私有成員的過程中,正是利用了這一性質。

  前面提到,在類的構造函數中可以爲類添加成員,通過這種方式定義的類成員,實際上共享了在構造函數內部定義的局部變量,這些變量就可以看作類的私有成員,例如:


<script language="JavaScript" type="text/javascript">
<!--
function class1(){
 var pp=" this is a private property"; //私有屬性成員pp
 function pm(){ //私有方法成員pm,顯示pp的值
  alert(pp);
 }
 this.method1=function(){
  //在公有成員中改變私有屬性的值
  pp="pp has been changed";
 }
 this.method2=function(){
  pm(); //在公有成員中調用私有方法
 }
}
var obj1=new class1();
obj1.method1();  //調用公有方法method1
obj1.method2();  //調用公有方法method2
//-->
</script>




  這樣,就實現了私有屬性pp和私有方法pm。運行完class1以後,儘管看上去pp和pm這些局部變量應該隨即消失,但實際上因爲class1是通過new來運行的,它所屬的對象還沒消失,所以仍然可以通過公開成員來對它們進行操作。

  注意:這些局部變量(私有成員),被所有在構造函數中定義的公有方法所共享,而且僅被在構造函數中定義的公有方法所共享。這意味着,在prototype中定義的類成員將不能訪問在構造體中定義的局部變量(私有成員)。

  要使用私有成員,是以犧牲代碼可讀性爲代價的。而且這種實現更多的是一種JavaScript技巧,因爲它並不是語言本身具有的機制。但這種利用變量作用域性質的技巧,卻是值得借鑑的。

  實現靜態成員

  靜態成員屬於一個類的成員,它可以通過“類名.靜態成員名”的方式訪問。在JavaScript中,可以給一個函數對象直接添加成員來實現靜態成員,因爲函數也是一個對象,所以對象的相關操作,對函數同樣適用。例如:


function class1(){//構造函數
}
//靜態屬性
class1.staticProperty="sample";
//靜態方法
class1.staticMethod=function(){
 alert(class1.staticProperty);
}
//調用靜態方法
class1.staticMethod();

  通過上面的代碼,就爲類class1添加了一個靜態屬性和靜態方法,並且在靜態方法中引用了該類的靜態屬性。

  如果要給每個函數對象都添加通用的靜態方法,還可以通過函數對象所對應的類Function來實現,例如:


//給類Function添加原型方法:show ArgsCount
Function.prototype.showArgsCount=function(){
 alert(this.length); //顯示函數定義的形參的個數
}
function class1(a){
 //定義一個類
}
//調用通過Function的prototype定義的類的靜態方法showArgsCount
class1. showArgsCount ();

  由此可見,通過Function的prototype原型對象,可以給任何函數都加上通用的靜態成員,這在實際開發中可以起到很大的作用,比如在著名的prototype-1.3.1.js框架中,就給所有的函數定義了以下兩個方法:


//將函數作爲一個對象的方法運行
Function.prototype.bind = function(object) {
 var __method = this;
 return function() {
  __method.apply(object, arguments);
 }
}
//將函數作爲事件監聽器
Function.prototype.bindAsEventListener = function(object) {
 var __method = this;
 return function(event) {
  __method.call(object, event || window.event);
 }
}

什麼是反射機制

  反射機制指的是程序在運行時能夠獲取自身的信息。例如一個對象能夠在運行時知道自己有哪些方法和屬性。

  在JavaScript中利用for(…in…)語句實現反射

  在JavaScript中有一個很方便的語法來實現反射,即for(…in…)語句,其語法如下:

for(var p in obj){
      //語句
}

  這裏var p表示聲明的一個變量,用以存儲對象obj的屬性(方法)名稱,有了對象名和屬性(方法)名,就可以使用方括號語法來調用一個對象的屬性(方法):

for(var p in obj){
      if(typeof(obj[p]=="function"){
             obj[p]();
      }else{
             alert(obj[p]);
      }
}

  這段語句遍歷obj對象的所有屬性和方法,遇到屬性則彈出它的值,遇到方法則立刻執行。在後面可以看到,在面向對象的JavaScript程序設計中,反射機制是很重要的一種技術,它在實現類的繼承中發揮了很大的作用。

  使用反射來傳遞樣式參數

  在Ajax編程中,經常要能動態的改變界面元素的樣式,這可以通過對象的style屬性來改變,比如要改變背景色爲紅色,可以這樣寫:

element.style.backgroundColor="#ff0000";

  其中style對象有很多屬性,基本上CSS裏擁有的屬性在JavaScript中都能夠使用。如果一個函數接收參數用用指定一個界面元素的樣式,顯然一個或幾個參數是不能符合要求的,下面是一種實現:

function setStyle(_style){
      //得到要改變樣式的界面對象
      var element=getElement();
      element.style=_style;
}

  這樣,直接將整個style對象作爲參數傳遞了進來,一個style對象可能的形式是:

var style={
      color:#ffffff,
      backgroundColor:#ff0000,
      borderWidth:2px
}

  這時可以這樣調用函數:

setStyle(style);

  或者直接寫爲:

setStyle({ color:#ffffff,backgroundColor:#ff0000,borderWidth:2px});

  這段代碼看上去沒有任何問題,但實際上,在setStyle函數內部使用參數_style爲element.style賦值時,如果element原先已經有了一定的樣式,例如曾經執行過:

element.style.height="20px";

  而_style中卻沒有包括對height的定義,因此element的height樣式就丟失了,不是最初所要的結果。要解決這個問題,可以用反射機制來重寫setStyle函數:

function setStyle(_style){
      //得到要改變樣式的界面對象
      var element=getElement();
      for(var p in _style){
            element.style[p]=_style[p];
      }
}

  程序中遍歷_style的每個屬性,得到屬性名稱,然後再使用方括號語法將element.style中的對應的屬性賦值爲_style中的相應屬性的值。從而,element中僅改變指定的樣式,而其他樣
<script type="text/javascript"> function ImgZoom(Id)//重新設置圖片大小 防止撐破錶格 { var w = $(Id).width; var m = 550; if(w < m) { return; } else { var h = $(Id).height; $(Id).height = parseInt(h*m/w); $(Id).width = m; } } window.onload = function() { var Imgs = $("content").getElementsByTagName("img"); var i=0; for(;i

本文轉自
http://www.6to23.com/tech/btkf/kfpt/java/200606/47427.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章