2014-10-02 88 views
1

該對象實現了一個模式來提供事件偵聽器。它至少可以在IE 11和Chrome中運行。爲什麼`this`不等於`Object`,爲什麼屬性`undefined`?

但我不明白爲什麼和我有兩個問題。

在按鍵事件監聽器中,有一個警報顯示this等於[object HTMLInputElement]this.elementundefined

  1. 爲什麼this不等於Object
  2. 爲什麼this.elementundefined? (請注意,在init方法初始化。)

看到這個JSFiddle

這裏是JavaScript:

function CustomEditor(id) { 
    'use strict'; 
    this.element = null; 
    this.id = id; 
    this.init(); 
}; 

CustomEditor.prototype.addEvent = function (event, callback) { 
    'use strict'; 
    return this.element.addEventListener(event, callback, false); 
}; 

CustomEditor.prototype.init = function() { 
    'use strict'; 
    this.element = document.getElementById(this.id); 
    this.addEvent('keypress', this.onCustomKeyPress); 
}; 


CustomEditor.prototype.onCustomKeyPress = function() { 
    'use strict'; 
    // alert("keypress event handler"); 
    this.style.backgroundColor = "#000"; 
    this.style.color = "#ff0"; 
    alert('this = ' + this + '\n\nthis.element = ' + this.element); 
}; 


// create and initialize custom editor 
ce = new CustomEditor('myInput1'); 
document.getElementById('myInput1').value = 'a'; 
alert('ce = ' + ce + '\n\nce.element = ' + ce.element); 

編輯:由@Bergi & @lombausch的意見,我瞭解我在this和上下文(週末戰士在這裏)的錯誤觀念。我對我的對象進行了以下修改,現在this具有我需要的上下文。 (我使用call而非bind這樣的代碼可與舊版瀏覽器。)

MyObj.prototype.addEvent = function (event, callback, caller) { 
    'use strict'; 
    if (typeof window.addEventListener === 'function') { 
     return this.element.addEventListener(event, function() { 
      callback.call(caller); 
     }, false); 
    } 
    // for older versions of IE, order of test is important 
    return this.element.attachEvent('on' + event, function() { 
     callback.call(caller); 
    }); 
}; 

JSFiddle

但是,一個新問題:什麼樣的變化已被該模式提出了onCustomKeypress到有權訪問事件接口/對象?

事件接口是事件偵聽器的第一個參數,但我似乎無法將它傳遞給回調函數。例如,這不起作用:

MyObj.prototype.onCustomKeyPress = function (e) { 
+1

我假設你的意思是「等於'ce'」,而不是「對象」? – Bergi 2014-10-02 11:00:30

+1

這就是事件偵聽器的工作方式,它們在綁定到的元素的上下文中調用。看到[這個問題](https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback)的解決方案 - 或者你真的想知道*爲什麼*? – Bergi 2014-10-02 11:02:42

+0

這對你來說總的來說是否令人困惑(就像大多數JavaScript新手一樣),或者特別是關於「嚴格使用」爲什麼沒有幫助? – 2014-10-02 11:02:51

回答

0

(我使用的呼叫,而不是綁定,使代碼可與舊版瀏覽器。)

爲什麼? bind顯然很簡單。如果您希望它可以與舊版瀏覽器一起使用,那麼只需在您的代碼中包含this simple polyfill

必須對onCustomKeypress訪問事件接口/對象的模式進行哪些更改?

無。問題仍然是您的addEvent函數,該函數現在可能會使用正確的上下文調用callback,但不帶參數。有兩種解決方案:

  • 使用arguments objectapply代替:

    …(…, function() { 
        callback.apply(caller, arguments); 
    } … 
    
  • 只是傳遞事件參數call - 它接受任何數目的正常參數範圍內後:

    MyObj.prototype.addEvent = function(event, callback, caller) { 
        'use strict'; 
        if (typeof window.addEventListener === 'function') { 
         this.element.addEventListener(event, function(e) { 
          callback.call(caller, e); 
         }, false); 
        } else { 
         // for older versions of IE, order of test is important 
         this.element.attachEvent('on' + event, function() { 
          callback.call(caller, window.event); 
         }); 
        } 
    }; 
    
+0

完美。謝謝。 (我已經將'e'作爲參數添加到匿名回調函數中,但是沒有將它作爲參數添加到'call'。 – Karl 2014-10-05 21:27:12

+0

剛纔我發佈了一個後續問題[here](http://stackoverflow.com/questions/28386665/how-to-use-removeeventlistener-when-event-handler-is-a-prototype-function)詢問如何使用'removeEventListener'。我想你可能知道答案。 – Karl 2015-02-07 20:01:48