Вызов метода объекта 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
, не прибегая к использованию глобальной переменной?
Ответы
Ответ 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();
}
});
};
}