Pesquisa de site

javascript - Pare de segurar 'this' em uma variável temporária


Estou continuamente tendo que manter this em uma variável temporária para poder acessá-lo em outras funções. Por exemplo, nos dois métodos abaixo, estou mantendo this em uma variável 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)
        }
    });
},

Existe alguma maneira de contornar isso ou eu poderia possivelmente usar apply?

Resposta #1

O ECMAScript 5 introduziu Function.bind()[docs], então ele é suportado apenas por navegadores mais recentes. Uma implementação alternativa pode ser encontrada na documentação que eu linkei. Se você a incluir no seu código, você também pode usar bind() nos outros navegadores (mais antigos).

Isso permite que você defina a que objeto this deve se referir na função. Então você poderia escrever:

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)
    });
},

Resposta #2

Acho que essa é a maneira mais simples de fazer isso. É o que eu faço (embora eu esteja escrevendo código GWT), para referenciar o this da função envolvente em uma função anônima interna.

Mesmo que algo como this.wrappingMethod.this fosse possível, armazenar o this em uma variável nomeada de acordo com seu gosto é muito mais legível (você poderia usar um nome mais descritivo, é claro), e (ainda assumindo que você de alguma forma poderia referenciar o escopo envolvente) será mais robusto, pois você poderia introduzir outro nível sem precisar reescrever todas as referências.