Chrome Extension добавляет прослушиватели событий для динамически создаваемых элементов [duplicate]

Другим случаем, когда NullReferenceExceptions может случиться, является (неправильное) использование оператора as :

class Book {
    public string Name { get; set; }
}
class Car { }

Car mycar = new Car();
Book mybook = mycar as Book;   // Incompatible conversion --> mybook = null

Console.WriteLine(mybook.Name);   // NullReferenceException

Здесь Book и Car являются несовместимыми типами; a Car не может быть преобразован / передан в Book. Когда этот сбой завершается неудачно, as возвращает null. Используя mybook после этого, вы вызываете NullReferenceException.

В общем случае вы должны использовать cast или as, как показано ниже:

Если вы ожидаете преобразования типа в всегда преуспевает (т. е. вы знаете, какой объект должен быть впереди времени), тогда вы должны использовать cast:

ComicBook cb = (ComicBook)specificBook;

Если вы не уверены в типе, но хотите попробовать , чтобы использовать его как определенный тип, затем используйте as:

ComicBook cb = specificBook as ComicBook;
if (cb != null) {
   // ...
}

54
задан sebas2day 3 April 2012 в 21:35
поделиться

6 ответов

Учитывая обновление исходного вопроса, похоже, что проблема связана с контекстом («this») при передаче обработчиков событий. Основы объясняются, например. здесь http://www.w3schools.com/js/js_function_invocation.asp

Простая рабочая версия вашего примера может читать

var doClick = function(event, additionalParameter){
    // do stuff with event and this being the triggering event and caller
}

element.addEventListener('click', function(event)
{
  var additionalParameter = ...;
  doClick.call(this, event, additionalParameter );
}, false);

См. также Javascript call () & amp; apply () vs bind ()?

2
ответ дан Community 31 August 2018 в 17:29
поделиться

this внутри doThings - это объект окна. Попробуйте это вместо:

var doThings = function (element) {
    var eventHandler = function(ev, func){
        if (element[ev] == undefined) {
            return;
        }

        element[ev] = function(e){
            func(e, element);
        }
    };

    return {
        eventHandler: eventHandler
    };
};
0
ответ дан jbabey 31 August 2018 в 17:29
поделиться

Я не понимаю точно, что ваш код пытается сделать, но вы можете сделать переменные доступными в любом обработчике событий, используя преимущества закрытия функций:

function addClickHandler(elem, arg1, arg2) {
    elem.addEventListener('click', function(e) {
        // in the event handler function here, you can directly refer
        // to arg1 and arg2 from the parent function arguments
    }, false);
}

В зависимости от вашей точной ситуации кодирования , вы можете почти всегда делать какой-то закрытие, сохраняя доступ к переменным для вас.

Из ваших комментариев, если вы пытаетесь выполнить это:

element.addEventListener('click', func(event, this.elements[i]))

Затем вы можете сделать это с помощью функции самоисполнения (IIFE), которая захватывает аргументы, которые вы хотите в закрытии, когда она выполняется и возвращает фактическую функцию обработчика событий:

element.addEventListener('click', (function(passedInElement) {
    return function(e) {func(e, passedInElement); };
}) (this.elements[i]), false);

Подробнее о том, как IIFE работает, см. эти другие ссылки:

Код обертки Javascript внутри анонимной функции

Выражение с мгновенной вызывной функцией (IIFE) В JavaScript - Передача jQuery

Каковы хорошие примеры использования JavaScript для выполнения анонимных функций?

Эта последняя версия, возможно, проще увидеть, что она делает как это:

// return our event handler while capturing an argument in the closure
function handleEvent(passedInElement) {
    return function(e) {
        func(e, passedInElement); 
    };
}

element.addEventListener('click', handleEvent(this.elements[i]));

Также можно использовать .bind() , чтобы добавить аргументы для обратного вызова. Любые аргументы, которые вы передадите .bind(), будут добавлены к аргументам, которые будут иметь сам обратный вызов. Итак, вы можете сделать это:

elem.addEventListener('click', function(a1, a2, e) {
    // inside the event handler, you have access to both your arguments
    // and the event object that the event handler passes
}.bind(elem, arg1, arg2));
65
ответ дан jfriend00 31 August 2018 в 17:29
поделиться

Что-то, что вы можете попробовать, это использовать метод bind, я думаю, что это достигает того, о чем вы просили. Если ничего другого, это все еще очень полезно.

function doClick(elem, func) {
  var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument
  diffElem.addEventListener('click', func.bind(diffElem, elem))
}

function clickEvent(elem, evt) {
  console.log(this);
  console.log(elem); 
  // 'this' and elem can be the same thing if the first parameter 
  // of the bind method is the element the event is being attached to from the argument passed to doClick
  console.log(evt);
}

var elem = document.getElementById('elem_to_do_stuff_with');
doClick(elem, clickEvent);
7
ответ дан Knight Yoshi 31 August 2018 в 17:29
поделиться
let obj = MyObject();

elem.someEvent( function(){ obj.func(param) } );

//calls the MyObject.func, passing the param.
-2
ответ дан RamenChef 31 August 2018 в 17:29
поделиться

Это старый вопрос, но общий. Итак, позвольте мне добавить это здесь.

С синтаксисом ES2015 вы можете добиться более сжатого пути:

function event_handler(event, arg) {
  console.log(event, arg);
}

element.addEventListener('click', (event) => event_handler(event, 'Here comes the argument'));
3
ответ дан SnnSnn 31 August 2018 в 17:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: