15

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

由于我将制作多个对象,因此我将无法创建像存储一样的“静态”。请帮助这个 javascript n00b ;-)

这是我的测试代码,您可以使用它来重现我的问题。我想要的是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();
4

3 回答 3

18

您的问题出在这一行:$('#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,然后它使用被单击的元素显式调用它作为this. 正在发生的事情是(稍微复杂一点的版本):

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

解决方案

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

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

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

$('#some-element').click(jQuery.proxy(this.doSomething, this));
于 2012-05-26T13:24:14.680 回答
11
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

于 2012-05-26T12:57:02.290 回答
3

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

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

... 你写:

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

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

$('#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(...).

于 2014-07-04T08:31:07.653 回答