Магистраль: правильный способ передачи 'this' ссылки на анонные функции при обратных вызовах успеха/ошибки
С учетом функции просмотра позвоночника ниже, каков правильный способ передачи this
(т.е. текущего представления) анонимной функции, определенной в обратных вызовах?
addSomething: function(e) {
var newSomething= this.model.somethings.create({
someProperty: xxx
}, {
success: function(m, response) {
this.doSomething(); //***HERE****
},
error: function(m, response) {
//Error
}
});
},
Без изменений и изменений, this
в функции anon устанавливается в окно.
Я могу установить ссылку как это:
var thisView = this;
а затем просто обратитесь к thisView
вместо this
в функцию anon, но это не выглядит очень элегантным. Есть ли лучший способ?
Ответы
Ответ 1
Чтобы лучше организовать мой код и решить эту проблему, я никогда не ставил успешные и обратные вызовы ошибок непосредственно в соответствии с моими вызовами. Я всегда разделял их на свои собственные функции. Это позволило мне сохранить код чистым, а также использовать метод _.bindAll
, чтобы убедиться, что у меня есть правильный контекст для this
.
SomeView = Backbone.View.extend({
initialize: function(){
_.bindAll(this, "createSuccess", "createError");
},
addSomething: function(e) {
var newSomething= this.model.somethings.create({someProperty: xxx}, {
success: this.createSuccess,
error: this.createError
});
},
createSuccess: function(m, response) {
this.doSomething();
},
createError: function(m, response) {
//Error
}
});
Ответ 2
Вы можете использовать call:
this.doSomething.call(this);
Или отправьте все, что хотите this
, в doSomething
Ответ 3
Вы также можете использовать соглашение that
:
addSomething: function(e) {
var that = this;
var newSomething= this.model.somethings.create({
someProperty: xxx
}, {
success: function(m, response) {
that.doSomething(); //***THAT HERE****
},
error: function(m, response) {
//Error
}
});
}
Это довольно распространенный шаблон в javascript, особенно когда контекст теряется с вложенными функциями. Вложенные функции имеют доступ к переменным во внешней функции и, следовательно, работают.
Подход Derick делает код более чистым, независимо от факта наличия дополнительных функций, но если вы не хотите, чтобы они использовали "это";)
Ответ 4
После того, как вы заболели, увидев слишком много "var that = this"; Я начал передавать атрибут "вид" в параметры вызова.
this.model.destroy({success:
function (model, resp, options) {
model.releaseLock(false);
window.location.href = options.view.getURLForModelID(model.get('id'));
},
error: function (model, resp, options) {
options.view.displayError(resp.message);
},
view: this
});
изменить
Другим вариантом, к которому я привык, является использование _.bind() для передачи текущего контекста.
this.model.destroy({success:
function (model, resp, options) {
model.releaseLock(false);
window.location.href = options.view.getURLForModelID(model.get('id'));
},
error: _.bind(function (model, resp, options) {
this.displayError(resp.message);
}, this),
});
Ответ 5
Вы можете передать контекст, не используя call
, bind
или apply
(или Lo-Dash), создав анонимную функцию, передав this
, а затем сразу же вызовите методы обработчика на прототипе объекта как показано в следующем примере CoffeeScript:
View = require('views/base/view')
module.exports = class LoginPageView extends View
template: require('./templates/login-page')
events:
'submit form': '_doLogin'
# Called when the template is bound using Chaplin
attach: ->
super
@$loginButton = @$('[name="login"]')
_doLogin: (evt) ->
evt.preventDefault()
@$loginButton.attr 'disabled', true
email = @$('[name="email"]').val()
password = @$('[name="password"]').val()
@model.save {email, password},
success: (model, response, options) =>
@_loginSuccess model, response, options
error: (model, response, options) =>
@_loginError model, response, options
_loginSuccess: (model, response, options) ->
# TODO: Implement method body
_loginError: (model, response, options) ->
# TODO: Implement method body
Возможно, это немного многословно с именами аргументов, а дополнительное закрытие, созданное анонимной функцией, не является лучшей реализацией по производительности, но, конечно же, немного легче понять и управлять при работе с людьми с разным уровнем квалификации.
Ответ 6
Вы также можете использовать $. proxy:
success: $.proxy(function(m, response) {
this.doSomething();
}, this),
error: function(m, response) {
//Error
}