以下為本站文章分類清單

  1. AJAXspacer
  2. ASPspacer
  3. CSSspacer
  4. Javascriptspacer
  5. Windows 應用程式spacer
  6. 網頁設計
  7. 評論、短文、雜文spacer
  8. 版主spacer
  9. 最新回應spacer

    以下為本頁本文內容

    addEventListener、attachEvent 和 this 關鍵字

    8/23 10' icon

    Photo by www.customicondesign.com/

    如果你是為了 IE 的 attachEvent 不能使用 this 關鍵字而來的,試著把 handler 裡的 this 改成 event.srcElement 就可以了, ex:obj.attachEvent('onfocus',function(){event.srcElement.select();});,然後,快回去趕案子吧。

    事件與控制

    為事件(Event)加上控制(handler),是個常用設計,舉個例子來說,假設有個文字欄位,操作時希望選取這個欄位時,欄位值會自動選取(反白),以方便新數值鍵入。看起來像

    內容很簡單,就是為 onclick 和 onfocus 這兩個事件加入控制,看起來像:

    <input type="text" value="click" name="txt" id="txt"
    	onclick="this.select();"
    	onfocus="this.select();" />

    好了,一份 HTML 文件中,如果有個十來個這種欄位,可能開始有人想用 javascript 來為每個欄位加入這些事件控制,於是我們需要的語法是 addEventListener (Firefox、Chrome、Safari、Opera) 或 attachEvent (IE),語法為:

    if (window.addEventListener){
    	//Mozilla 事件沒有 on 開頭
    	window.addEventListener('load',helloAudi, false);
    }else if (window.attachEvent){
    	window.attachEvent('onload',helloAudi);
    }
    
    function helloAudi(){
    	.....
    }
    
    function helloAudi_1(msg){
    	alert(msg);
    }
    

    handlerName 是一個 function,把 function 的名稱寫進去即可,如上例,不用加括號。但,這個寫法,不可以加參數,也就是不能傳遞參數到 helloAudi() 中,例如要加入 helloAudi_1 時,那寫法改一下,在 handlerName 這裡直接使用 function() 陳述,如:

    if (window.addEventListener){
    	//Mozilla 事件沒有 on 開頭
    	window.addEventListener('load',function(){helloAudi_1('謝謝');}, false);
    }else if (window.attachEvent){
    	window.attachEvent('onload',function(){helloAudi_1('謝謝');});
    }

    當然你可以為其他物件的事件加入控制,例如一開始提到的 this.select() 一樣

    var obj=document.getElementById('txt');
    if (window.addEventListener){
    	obj.addEventListener('focus',function(){this.select();}, false);
    	obj.addEventListener('click',function(){this.select();}, false);
    }else if (window.attachEvent){
    	obj.attachEvent('onfocus',function(){this.select();});
    	obj.attachEvent('onclick',function(){this.select();});
    }

    本來,事情到這裡就結束了,不過實作卻發現,在 IE 上,this 關鍵字失效,正確的說,是 this 關鍵字不再是代表我們所認知的那個物件,而是統一指向最上層的 window 物件

    <input type="text" value="click" name="txt1" id="txt1" />
    
    <script type="text/javascript">
    var obj=document.getElementById('txt1');
    if (window.addEventListener){
    	obj.addEventListener('click',function(){alert(this.id);}, false);
    }else if (window.attachEvent){
    	obj.attachEvent('onclick',function(){alert(this.id);});
    }
    

    上面的例子,在 Firefox / Chrome / IE9 下執行均顯示 txt1,在 IE9 以前的 IE 版本,則顯示 undefined。原因很簡單,對 this 的解讀不同。

    this 關鍵字

    this 是個有趣的關鍵字,是一種很口語化的關鍵字,但也讓很多人搞混,要了解 this 關鍵字,由生活中去體會即可,舉例來說

    好了,相信你能舉一反三了,在生活中,很多情況,我們不需要再明確指定目標,而是簡單用"這個"、"這裡"、"這O"來代替就很清楚能指出想表達的物件。

    同樣的,在程式語言裡,this 也有相同功效,例如:

    <img src="hello.jpg" onmouseover="this.src='hello1.jpg';" />

    試著用口語把上述內容說出來

    影像 來源是hello.jpg 在滑鼠移過去時="這個來源是hello1.jpg"

    以一句比較學術的話來說明 this

    this 代表目前所處物件或正作用中物件

    既然你身在其中,當然用"這個"就能代表想指定的物件,而不需要大費周折指定物件名稱或id等,同理延伸,要指定作用物件以外的物件,就必需清楚而明確的給予定義,例如使用 document.getElementById(id) 或流行的 $('#id')

    IE 在搞什麼?

    回到一開始的問題,透過 attachEvent,在參數中使用 this 為什麼失效呢?理由很簡單,就是認定"作用中物件"不同,IE 認為執行 window.attachEvent 動作時,作用中物件是 window,所以 this 也就代表 window,也就是,在指定事件時,IE 把整個物件代入到 this 關鍵字中,而非謹謹是把 this 這個字寫入事件裡,因此造成和設計者想像有所不同。

    這種解讀也不能算錯,只不過和直觀的設計有所不同,但 DOM 裡實際上存在很多類似情況,也就是不知道現在"作用中物件"是那一個,類似的情況,在"避免子物件的 onclick 事件同時引發父物件事件"這篇文章中有比較詳細說明。

     

    以下為文章回應區

    同意轉載,不過麻煩看一下轉載需知

    給個回應
    姓名:
    佈落格網址:
      如果您是要發問問題, 最好有個問題測試的網址, 這樣比較容易找到您問題所在, 謝謝
    內容: