Подтвердить что ты не робот

Могу ли я получить доступ к другому в lambda TypeScript?

В typescript я могу написать что-то вроде этого:

$('#something').fadeOut(400, (): void => {
    this.invokeAnotherMethod();
});

При компиляции TypeScript автоматически указывает, что это указывает на мой класс, а не на закрытую функцию:

var _this = this;
$('#something').fadeOut(400, function() {
    _this.invokeAnotherMethod();
});

Однако, как насчет того, когда мне нужно получить доступ к реальному, а не внешнему _this? Есть ли синтаксис для ссылки на него? Например, как я мог написать код, который бы скомпилировал следующее:

var _this = this;
$('#something').fadeOut(400, function() {
    $(this).data('specialhide', true);
    _this.invokeAnotherMethod();
});

Возможно ли это?

4b9b3361

Ответ 1

Вам нужно будет избежать синтаксиса толстой стрелки, чтобы сделать это, так как вы не хотите сохранять лексическую область this.

var _me = this;
$('#something').fadeOut(400, function () {
    _me.invokeAnotherMethod();
    $(this).data('specialhide', true);
});

В этом примере я использовал _me, а не _this, чтобы избежать столкновений с TypeScript сгенерированными переменными. Я также избегал self, чтобы избежать путаницы с window.self (спасибо RockResolve).

The Why!

В спецификации ECMAScript 6 указаны определения функции стрелки - это язык, на котором язык TypeScript использовал эту функцию. Когда TypeScript будет нацелен на ECMAScript 6 в будущем, он останется в синтаксисе () =>, поэтому они не смогут заставить его работать с обоими контекстами this, не нарушая будущей совместимости.

Даже если бы вы могли представить, как они могли бы сменить компилятор TypeScript, чтобы сделать как _this, так и this доступными в ECMAScript 3 или 5, это фактически станет проблемой в версии 6.

Ответ 2

Я понял выход, как описано здесь в моем ответе: Как сохранить лексическую область в TypeScript с функцией обратного вызова

Это лучший способ добиться закрытия, которое Стив Фентон сделал в своем ответе. Я предпочитаю его, потому что использование документов подписи метода.

В принципе, используйте такой метод:

fadeOutLambda(outerThis: YourClass): {(d: number, i: number): number}{
    return function(d: number, i: number){
        // Put your "fadeOut" logic here
        // refer to "this" to mean the dynamically scoped "this"
        // refer to "outerThis" to refer to the class instance
        alert(outerThis); // lexically scoped class instance
        alert(this); // dynamically scoped context caller
        return 999;
    }
}

Ответ 3

Позвольте мне предоставить другое решение, не использующее лямбда. Вы можете прикрепить это свойство как свойство (называемое мной в этом примере).

class MyClass
{
    constructor()
    {
        var button: HTMLElement = document.getElementById("buttonID");
        (button as any).me = this;
        button.onclick = this.buttonClick;
    }

    private buttonClick(e): boolean
    {
        var me: MyClass = (this as any).me;

        // Implementation using this (the button) and me (the class)

        return false;
    }
}