Javascript回调丢失了“this”

Javascript callbacks losing 'this'

本文关键字:this 回调 Javascript      更新时间:2023-09-26

我有一个发行者,我丢失了这个对象中的this。以下一段 JavaScript 的输出给了我"some-id",然后undefined。当我在回调函数中使用this时,范围超出了对象,它不能再使用this了。如何让回调使用"this"或至少可以访问对象?

由于我将创建多个对象,因此我将无法创建像存储这样的"静态"。

这是我的测试代码,您可以使用它来重现我的问题。我想要的是CheckBox.doSomething()返回this.id的值,该值应与此测试用例的some-id匹配。

function CheckBox(input_id) {
    this.id = input_id;
    this.doSomething();
    $('#some-element').click(this.doSomething);
}
Checkbox.prototype.doSomething = function() {
    alert(this.input_id);
}
var some_box = new CheckBox('some-id');
some_box.doSomething();
$('#some-element').click();

什至无法让它按照我想要的方式工作:

function CheckBox2(input_id) {
    this.id = input_id;
    alert(this.id);
}
CheckBox2.prototype.doSomething = function() {
    alert(this.input_id);
}
var some_box = new CheckBox2('some-id');
some_box.doSomething();

你的问题出在这条线上: $('#some-element').click(this.doSomething);

为什么这是一个问题

JavaScript 方法不知道应该分配给this的对象,它是在显式调用(使用 myFunction.call(obj) )或隐式调用(使用 obj.myFunction() 调用时)时设置的。

例如:

var x = {
    logThis: function () {
        console.log(this);
    }
};
x.logThis(); // logs x
x.logThis.call(y); // logs y
var func = x.logThis;
func(); // logs window: the fallback for when no value is given for `this`

在您的情况下,您将this.doSomething传递给 jQuery,然后 jQuery 使用单击的元素作为 this 的值显式调用它。正在发生的事情是(稍微复杂的版本)这个:

var callback = this.doSomething;
callback.call(anElement, anEvent);

解决方案

您需要确保使用正确的值 this 调用doSomething。您可以通过将其包装在另一个函数中来做到这一点:

var cb = this;
$('#some-element').click(function() {
    return cb.doSomething();
});

jQuery提供了一个proxy函数,让你可以更简单地做到这一点:

$('#some-element').click(jQuery.proxy(this.doSomething, this));
function CheckBox(input_id) {
    this.id = input_id;
    this.doSomething = $.proxy( this.doSomething, this );
    $('#some-element').click(this.doSomething);
}

它的"javascript等效物"是Function#bind但并非在每个浏览器中都可用,并且由于您似乎正在使用jQuery,因此我正在使用jQuery等效$.proxy

其他人已经解释了问题的原因以及如何使用 jQuery 修复它。剩下的就是如何使用标准JavaScript修复它。而不是。。。

$('#some-element').click(this.doSomething);

。你写:

document.getElementById('some-element').addEventListener('click', this.doSomething.bind(this));

这改变了doSomething内部this的上下文。您也可以使用匿名函数来做到这一点 - 而不是...

$('#some-element').click(function(event) {
    console.log(this);
});

。你写:

document.getElementById('#some-element').addEventListener('click', (function(event) {
    console.log(this);
}).bind(this));

这在有很多回调的项目中对我来说非常有用,例如在 Node.js(您不必关心过时的浏览器)。

编辑:getElementById()addEventListener()而不是$(...).click(...)