Подтвердить что ты не робот

Вызов метода объекта javascript из обратного вызова

Я определяю следующий MyClass и его методы у пользователя script:

function MyClass() {
    this.myCallback = function() {
        alert("MyClass.myCallback()");
    };

    this.startRequest = function() {
        GM_xmlhttpRequest({
            'method': 'GET',
            'url': "http://www.google.com/",
            'onload': function (xhr) {
                myClassInstance.myCallback();
            }
        });
    };
}

var myClassInstance = new MyClass();
myClassInstance.startRequest();

Этот script работает, и метод myCallback() вызывается после завершения GM_xmlhttpRequest.

Однако он работает только потому, что обратный вызов onload ссылается на глобальную переменную myClassInstance. Если я обновляю обратный вызов onload на:

'onload': function (xhr) {
    this.myCallback();
}

Затем я получаю ошибку (Chrome):

Uncaught TypeError: Object [object DOMWindow] не имеет метода myCallback.

Кажется, что this оценивается в неправильном контексте.

Есть ли способ вызвать метод myCallback() myClassInstance, не прибегая к использованию глобальной переменной?

4b9b3361

Ответ 1

Сохраните правильный this, когда он находится в области видимости, в переменную. Затем вы можете ссылаться на него позже:

 this.startRequest = function() {
     var myself = this;
     GM_xmlhttpRequest({
         'method': 'GET',
         'url': "http://www.google.com/",
         'onload': function (xhr) {
             myself.myCallback();
         }
     });
 };

Ответ 2

Самое простое решение, как уже указывалось, создает псевдоним для this, который остается в области видимости. Наиболее популярными именами переменных для псевдонима являются такие вещи, как self или that, но что-то действительно работает.

Другая альтернатива (которая может быть или не лучше, в зависимости от варианта использования) связывает этот метод с "простой" функцией и использует это вместо:

var f = this.callback.bind(this);

...
'onload': function(){
    f();
}

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

Ответ 3

Сохраните ссылку на экземпляр и используйте его:

function MyClass() {
    this.myCallback = function() {
        alert("MyClass.myCallback()");
    };

    var instance = this;

    instance.startRequest = function() {
        GM_xmlhttpRequest({
            'method': 'GET',
            'url': "http://www.google.com/",
            'onload': function (xhr) {
                instance.myCallback();
            }
        });
    };
}