Отложенные изменения JQuery "this"
Я пытаюсь, чтобы объект javascript запускал отложенный метод, и когда он .done() вызывает функцию в том же самом объекте. У меня проблемы, потому что "this" становится отложенным объектом вместо объекта, который его вызвал.
PageObject.prototype.successFunction = function() {
console.log(arguments);
return console.log(this.name + " Success function called");
};
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done(this.successFunction);
};
var pg = new PageObject();
pg.loadPage("test.html");
Как отправить "this" в функцию successFunction? Этот объект PageObject также будет расширен другими, поэтому знание "this" при запуске successFunction будет очень удобным.
Кажется простым и, вероятно, имеет простой ответ. Я смотрел в .apply(), но я не уверен, что это помогло. Этот пост при переполнении стека был полезен немного, но он сломался, как только я положил его в функцию .done().
Функции как параметры (с параметрами) - JavaScript
Ответы
Ответ 1
jQuery proxy
вернет функцию, привязанную к определенному контексту:
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done($.proxy(this.successFunction, this));
};
Существует также ES5 bind
, который работает аналогичным образом, но его нужно подкрепить в старых браузерах.
PageObject.prototype.loadPage = function(url) {
return $.when($.mobile.loadPage("pages/" + url))
.done(this.successFunction.bind(this));
};
apply
и call
могут немедленно выполнять функцию с указанным контекстом, но proxy
и bind
возвращают функцию, которая может быть использована позже или передана другим функциям.
Ответ 2
this
"переменная" в JavaScript называется "вызывающим объектом" и определяется, когда вызывается ее встроенная функция (а не когда она определена). Его можно установить несколькими способами:
- Вы можете установить его с помощью оператора
.
(например, myObject.myFunction()
)
- Вы можете установить его с помощью методов
call()
или apply()
- Вы можете (под ES5) связывать его постоянно, используя метод
bind()
- Он будет по умолчанию глобальным объектом, если ни один из вышеперечисленных методов не установит его в нечто другое
Важно понять, что (помимо метода 3 выше), все это о том, как вызывается функция при вызове, а не о том, как она ссылается, а не о том, как она хранится, а не о том, где она была создана.
В вашем случае вы передаете this.successFunction
в качестве ссылки на функцию, которую должен вызывать jQuery, но он не называет его таким образом (потому что он просто получил ссылку на функцию, а не какую-либо информацию о том, как это функция должна быть вызвана).
Есть несколько причудливых трюков, которые вы можете использовать с методами jQuery $.proxy()
или ES5 .bind()
, но когда дело доходит до него, самый простой способ справиться с этим - просто сохранить this
и использовать оболочку функции:
PageObject.prototype.loadPage = function(url) {
var self = this;
return $.when($.mobile.loadPage("pages/" + url))
.done(function () { self.successFunction(); });
};
Обратите внимание, что мы используем метод 1 для явного привязки successFunction
вызывающего объекта к тому же, что и вызывающий объект loadPage. Он короткий, простой, понятный, отлично работает под ES3 и не зависит от jQuery.