如何在回调中访问正确的“ this”?

我有一个注册事件处理程序的构造函数:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

但是,我无法data在回调内部访问已创建对象属性。看起来好像this不引用创建的对象,而是引用另一个对象。

我也尝试使用对象方法而不是匿名函数:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

但是也有同样的问题

如何访问正确的对象?

番长Harry2020/03/09 21:04:09

使用bind()或使用箭头函数代替访问它。

乐蛋蛋2020/03/09 21:04:09

我们不能将其绑定到setTimeout(),因为它总是与全局对象(Window)一起执行,如果您想访问this回调函数中的上下文,则通过使用bind()回调函数,我们可以实现为:

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);
用户70493023002020/03/09 21:04:09

所有这些都是调用方法的“魔术”语法:

object.property();

当您从对象获取属性并一次性调用它时,该对象将成为方法的上下文。如果您调用相同的方法,但是在单独的步骤中,则上下文将改为全局作用域(窗口):

var f = object.property;
f();

当您获得方法的引用时,它不再附加到对象上,而只是对普通函数的引用。当您将引用用作回调时,也会发生相同的情况:

this.saveNextLevelData(this.setAll);

那是将上下文绑定到函数的地方:

this.saveNextLevelData(this.setAll.bind(this));

如果您使用的是jQuery,则应改用$.proxy方法,因为bind并非所有浏览器都支持方法

this.saveNextLevelData($.proxy(this.setAll, this));