停止在临时变量中保存'this'

时间:2011-06-15 13:24:58

标签: javascript

我不得不在临时变量中保存this以便在其他函数中访问它。例如,在下面的两种方法中,我将this保留在that变量中:

startTimer: function () {
    var that = this;

    if ($('#defaultCountdown:hidden'))
        $('#defaultCountdown').show('slow');
    shortly = new Date();
    shortly.setSeconds(shortly.getSeconds() + 5);
    $('#defaultCountdown').countdown('change', { until: shortly,
        layout: '<ul id="errorList"><li>Next update in <b>{snn}</b> {desc}</li></ul>',
        description: 'seconds',
        onExpiry: function () {
            that.performUpdate();
        }
    });
},
performUpdate: function () {
    var that = this;

    this.message.fetch({
        success: function () {
            $('#calleesStatuses').html('');
            that.callees.refresh(that.message.get("Callees"));
            $('#defaultCountdown').hide('slow');
            that.startTimer();
        },
        error: function (request, settings) {
            that.killCountDown();
            showErrorMessage(request.responseText)
        }
    });
},

无论如何还是可以使用apply吗?

5 个答案:

答案 0 :(得分:4)

ECMAScript 5引入了Function.bind()[docs],因此只有较新的浏览器才支持它。可以在我链接到的文档中找到替代实现。如果您将其包含在代码中,则也可以在其他(较旧的)浏览器中使用bind()

它允许您设置函数中应引用的对象this。所以你可以写:

performUpdate: function () {    
    this.message.fetch({
        success: function () {
            $('#calleesStatuses').html('');
            this.callees.refresh(this.message.get("Callees"));
            $('#defaultCountdown').hide('slow');
            this.startTimer();
        }.bind(this),
        error: function (request, settings) {
            this.killCountDown();
            showErrorMessage(request.responseText)
        }.bind(this)
    });
},

答案 1 :(得分:1)

不,没有。 this的值在闭包中将不同于闭包定义的范围,因此唯一的方法是使它更清洁是在对象级别定义它,所以至少你只需要为每个对象做一次,看起来你已经在做了。

编辑:

找出“不存在”,因为bind是一种有效的替代方案,并且存在可比性实施(参见其他答案)。虽然我个人认为var self = this;更清洁,你只需要为每个对象定义一次,但这是一个偏好的问题。

答案 2 :(得分:1)

我认为这是最简单的方法。这就是我所做的(尽管我正在编写GWT代码),以引用内部匿名函数中的包装函数的this

即使像this.wrappingMethod.this这样的东西是可能的,将this存储在根据您的口味命名的变量中也更具可读性(您可以使用更具描述性的名称,当然),并且(仍假设你以某种方式冷引用包装范围)它会更强大,因为你可以引入另一个级别而不必重写所有引用。

答案 3 :(得分:0)

我想这并不舒服,但如果原始this是您可以执行startTimerkillCountdown等功能的唯一上下文,那就不是真的了。我建议给它一个更有意义的名字,比如timer或其他什么。实际上,this只是一个方便的关键字,用于引用我们正在执行的任何内容的所有者,并且应该随着所有者的更改而更改。如果“this / that”变得难以阅读,解决方案是将名称从that更改为更具语义意义的名称。

答案 4 :(得分:0)

您所做的是JavaScript中的标准模式,但使用self代替that是传统的模式。但您可以使用bind()方法,如下所示:

onExpiry: performUpdate.bind(this);

如果您正在使用扩展Function原型的框架来包含它,或者您的Javascript解释器已经足够了。 (bind在幕后创建了相同类型的匿名函数,但由于它必须处理各种特殊情况,因此可能效率较低。)