2014-10-02 2 views
1

Этот объект реализует шаблон для прослушивания событий. Он работает как минимум в IE 11 и Chrome.Почему `this` не равно` Object` и почему свойство `undefined`?

Но я не понимаю, почему и у меня есть 2 вопроса.

В нажатие клавиши прослушивателя событий, есть предупреждение, что показывает, что this равно [object HTMLInputElement] и this.element является undefined.

  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); 

EDIT: Из комментариев @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 », а не« Object »? – Bergi

+1

Именно так работают слушатели событий, они вызываются в контексте элемента, к которому они привязаны. См. [Этот вопрос] (https://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) для решений - или вы действительно хотите знать *, почему *? – Bergi

+0

Это сбивает вас с толку в целом (как и у большинства новичков JavaScript), или конкретно в отношении того, почему '' use strict'' не помогает? –

ответ

0

(я использую вызов, а не связываются с тем, что код работает со старыми браузерами.)

Почему? bind намного проще. Если вы хотите, чтобы он работал со старыми браузерами, просто укажите this simple polyfill где-нибудь в вашем коде.

Какие изменения должны быть внесены в шаблон для onCustomKeypress для доступа к интерфейсу/объекту события?

Отсутствует. Проблема по-прежнему заключается в вашей функции addEvent, которая теперь может вызывать callback с правильным контекстом, но без аргументов.Два решения:

  • Используйте кнопки arguments object и apply вместо:

    …(…, 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

+0

Только что я опубликовал следующий вопрос [здесь] (http://stackoverflow.com/questions/28386665/how-to-use-removeeventlistener-when-event-handler-is-a-prototype-function), спрашивающий, как использовать 'removeEventListener'. Я думал, что вы можете знать ответ. – Karl