Javascript回调失去'这个'

时间:2012-05-26 12:54:57

标签: javascript object callback this scope

我有一个发行人,我在这个'对象'中失去了'this'。以下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();

3 个答案:

答案 0 :(得分:17)

您的问题在于这一行:$('#some-element').click(this.doSomething);

为什么这是一个问题

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

例如:

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` 传递给jQuery,然后使用被单击为this.doSomething的值的元素显式调用它。发生了什么(稍微复杂一点):

this

解决方案

您需要确保使用var callback = this.doSomething; callback.call(anElement, anEvent); 的正确值调用doSomething。您可以通过将其包装在另一个函数中来实现:

this

jQuery提供了proxy功能,让您可以更简单地执行此操作:

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

答案 1 :(得分: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

答案 2 :(得分:2)

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

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

...你写道:

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

这会更改thisdoSomething的内容。您也可以使用匿名函数来代替...

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