1. 程式人生 > >e = e || window.event的區別及用法。

e = e || window.event的區別及用法。

e = e || window.event  在做事件處理時,用於區分IE和其他瀏覽器事件物件。

下面連結為事件物件的參考資料:

  http://wenku.baidu.com/view/400a89f4f61fb7360b4c65ca.html

<!DOCTYPE HTML>
<html>

    <head>
        <title></title>
        <style type="text/css">
            #aa {
                border: 1px solid #000;
                width: 100px;
                height: 40px;
                margin-top: 50px;
            }
            
            #bb {
                border: 1px solid #000;
                width: 500px;
                height: 40px;
                margin-top: 50px;
            }
            
            #cc {
                border: 1px solid #000;
                width: 500px;
                height: 40px;
            }
        </style>
    </head>

    <body>
        <div id="aa"></div>
        <div id="bb">dfdfddfsd</div>
        <div id="cc">gregreger</div>

        <script type="text/javascript">
            /*JS的event.srcElement與event.target(觸發事件物件)
                IE下,event物件有srcElement屬性,但是沒有target屬性;
                Firefox下,event物件有target屬性,但是沒有srcElement屬性.但他們的作用是相當的,即:
                firefox 下的 event.target = IE 下的 event.srcElement
                解決方法:使用obj = event.srcElement ? event.srcElement : event.target;
                或:var evtTarget = event.target || event.srcElement;
            */

            //event.srcElement:表示的當前的這個事件源。
            //
            //event.srcElement.parentNode:表示當前事件源的父節點。
            //
            // parentNode:父節點,也就是上一層的節點。可以是任何一個標籤。
            //
            //event.srcElement.firstChild:當前事件的第一個節點,如果節點是input,通過event.srcElement.firstChild.value就可以獲取此input的值。
            //
            //event.srcElement.parentElement:是指在滑鼠所在物件的上一個物件。
            //
            //event.srcElement.children:當前節點下物件的個數,有多個的話就是個陣列,如當前節點下有2個input的物件,要獲取這兩個可以用event.srcElement.children[0] 與 event.srcElement.children[1]分別獲取。
            //            

            document.getElementById("aa").onclick = function(e) {
                if(e) console.log(e.toString()); // IE6/7/8 e為undefined  IE9中e為W3標準事件物件。
                //e = window.event;
                console.log(e.srcElement.tagName || e.currentTarget.tagName);
            };
            /*  element.onXXX方式(比較古老,不推薦使用)
            這種方式新增事件IE6/7/8只支援window.event不支援引數傳入,
            Firefox只支援引數傳入不支援其它方式。
            IE9/Opera/Safari/Chrome 兩種方式都支援。
            */

            var d4 = document.getElementById('bb');

            function clk(e) {
                alert(e); // 所有瀏覽器彈出的資訊框顯示都是事件物件。
                alert(e.srcElement.tagName || e.currentTarget.tagName);
                e = e || window.event;
                alert(e); // IE6/7/8中和上個e彈出相同的物件。
            };
            
            //addEventListener() 用於向指定元素新增事件。 
            //            引數說明:tr件,比如 click mouseenter mouseleave 
            //fn 回撥函式 
            //useCaption 用於描述是冒泡還是捕獲。預設值是false,即冒泡傳遞。 
            //當值為true,就是捕獲傳遞。 
            if(d4.addEventListener) {
                d4.addEventListener('click', clk, false);
                alert("addEventListener");
            };
            if(d4.attachEvent) {
                d4.attachEvent('onclick', clk);
                alert("attachEvent");
            };
            /*  addEventListener、attachEvent方式(推薦使用)


            結論:
            通常事件控制代碼裡有這句話:e = e || window.event;
            但是在這種呼叫方式(addEventListener、attachEvent方式)中沒什麼作用,
            這是什麼原因呢?上邊參考文章的總結裡指出了原因,即:
            “IE6/7/8支援通過window.event獲取物件,
            通過attachEvent方式新增事件時也支援事件物件作為控制代碼第一個引數傳入”
            因為IE6/7/8在attachEvent方式新增事件時同時支援兩種方式,所以事件控制代碼中的引數e在
            IE6/7/8中會自動轉換為window.event。
            這麼以來,這句e = e || window.event;在此處就不需要了(個人結論)。


            */

            /*  
            在編寫跨瀏覽器的函式庫時,IE和標準事件物件的屬性的差異的問題需要解決。
            下邊抽出相關程式碼,討論這個問題在這裡的體現。
            */
            var _E = {
                BindEvent: function(object, fun) {
                    if(arguments.length == 1) {
                        fun = arguments[0];
                        object = null;
                    }
                    var args = Array.prototype.slice.call(arguments, 2);
                    return function(event) {
                        return fun.apply(object, [fixEvent(event)].concat(args));
                    }
                }
            };

            function fixEvent(event) { // 統一不同瀏覽器的event物件
                if(event) return event;
                event = window.event;
                event.pageX = event.clientX + getScrollLeft(event.srcElement);
                event.pageY = event.clientY + getScrollTop(event.srcElement);
                event.target = event.srcElement;
                event.stopPropagation = stopPropagation;
                event.preventDefault = preventDefault;
                var relatedTarget = {
                    "mouseout": event.toElement,
                    "mouseover": event.fromElement
                }[event.type];
                if(relatedTarget) {
                    event.relatedTarget = relatedTarget;
                }

                return event;
            };

            function stopPropagation() {
                this.cancelBubble = true;
            };

            function preventDefault() {
                this.returnValue = false;
            };

            // 測試程式碼如下
            function get(ev) {
                alert(ev.pageX);
            }
            var cc = document.getElementById("cc");
            var clickHandler = _E.BindEvent(get);
            //    cc.attachEvent('onclick', clickHandler); // IE6/7/8下測試
            /*
            結果點選id為cc的div元素後,彈出undefined。說明ev.pageX根本不存在。
            可是我們在fixEvent()裡已經做了事件物件的統一工作。
            除錯會發現:fixEvent()裡if (event) return event;這句是執行後就直接return了,
            這裡的event按照道理說應該是undefined,但是事實並不是。


            //
            至於原因個人覺得就是這裡:因為IE6/7/8在attachEvent方式新增事件時同時支援兩種方式,
            所以事件控制代碼中的引數會自動轉換為window.event。也就是說引數不是undefined
        
            //
            所以在這裡用if (event) return event;判斷事件物件不妥。
            (說明:fixEvent()這段程式碼參考自部落格園裡cloudgamer的函式庫,
             他裡邊就是這種寫法,個人覺得有錯誤,希望有興趣的朋友也做做驗證)
            */
        </script>
    </body>

</html>