主干:正确的传递方式'this'在成功/错误回调中引用匿名函数

Backbone: Correct way of passing 'this' reference to anon functions in success/error callbacks

本文关键字:回调 错误 引用 函数 成功 方式 this 主干      更新时间:2023-09-26

给定下面的骨干视图函数,将this(即当前视图)传递给回调中定义的匿名函数的正确方法是什么?

addSomething: function(e) {
    var newSomething= this.model.somethings.create({
        someProperty: xxx
    }, {
        success: function(m, response) {
            this.doSomething(); //***HERE****
        },
        error: function(m, response) {
            //Error
        }
    });
},

如果没有和更改,则将anon函数中的this设置为窗口。

我可以像这样设置一个引用:

var thisView = this;

,然后在匿名函数中只引用thisView而不是this,但这似乎不是很优雅。有没有更好的办法?

为了更好地组织代码并解决这个问题,我从未将成功和错误回调直接内联到调用中。我总是把它们分成各自的功能。这让我保持代码整洁,并使用_.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
  }
});

你可以使用call:

this.doSomething.call(this);

或者把this放到doSomething

您也可以使用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的方法使代码更干净,不管有额外的函数,但如果你不想要它们,使用'that';)

Backbone有一个内置的方法来处理这个问题:'context'属性。

this.model.destroy({
    success: function (model, resp, options) {
        model.releaseLock();
        window.location.href = this.getURLForModelID(model.get('id'));
    },
    error: function (model, resp, options) {
        this.displayError(resp.message);
    },
    context: this
});

你可以传递上下文似乎不使用call, bindapply(或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

参数名称可能有点冗长,并且匿名函数创建的额外闭包不是最佳的实现性能,但是当与不同技能水平的个体一起工作时,它肯定更容易掌握和管理。

您也可以使用$.proxy:

        success: $.proxy(function(m, response) {
            this.doSomething(); 
        }, this),
        error: function(m, response) {
            //Error
        }