Não tenho certeza da melhor abordagem para lidar com o escopo "this" no TypeScript.
Aqui está um exemplo de um padrão comum no código que estou convertendo para TypeScript:
class DemonstrateScopingProblems {
private status = "blah";
public run() {
alert(this.status);
}
}
var thisTest = new DemonstrateScopingProblems();
// works as expected, displays "blah":
thisTest.run();
// doesn't work; this is scoped to be the document so this.status is undefined:
$(document).ready(thisTest.run);
Agora, eu poderia mudar a chamada para ...
$(document).ready(thisTest.run.bind(thisTest));
... que funciona. Mas é meio horrível. Isso significa que o código pode ser compilado e funcionar bem em algumas circunstâncias, mas se esquecermos de vincular o escopo, ele será interrompido.
Eu gostaria de uma maneira de fazer isso dentro da classe, de modo que, ao usar a classe, não precisemos nos preocupar com o escopo de "this".
Alguma sugestão?
Atualizar
Outra abordagem que funciona é usar a seta grande:
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
alert(this.status);
}
}
Essa é uma abordagem válida?
typescript
this
Jonathan Moffatt
fonte
fonte
Respostas:
Você tem algumas opções aqui, cada uma com suas próprias compensações. Infelizmente, não existe uma melhor solução óbvia e isso realmente dependerá do aplicativo.
Encadernação automática de classe,
conforme mostrado em sua pergunta:
this
contexto em vez de cada site de chamada criar um novo encerramento na chamada.this
contextosuper.
Function.bind
Também como mostrado:
Seta grande
no TypeScript (mostrada aqui com alguns parâmetros fictícios por motivos explicativos):
fonte
Outra solução que requer alguma configuração inicial, mas compensa com sua luz invencível, literalmente sintaxe de uma palavra, é usar os Decoradores de Método para vincular métodos JIT por meio de getters.
Eu criei um repositório no GitHub para mostrar uma implementação dessa ideia (é um pouco demorado para caber em uma resposta com suas 40 linhas de código, incluindo comentários) , que você usaria simplesmente como:
Eu não vi isso mencionado em nenhum lugar ainda, mas funciona perfeitamente. Além disso, não há nenhuma desvantagem notável nessa abordagem: a implementação desse decorador - incluindo alguma verificação de tipo para segurança de tipo em tempo de execução - é trivial e direta e vem com essencialmente zero sobrecarga após a chamada do método inicial.
A parte essencial é definir o seguinte getter no protótipo da classe, que é executado imediatamente antes da primeira chamada:
Fonte completa
A ideia também pode ser levada um passo adiante, fazendo isso em um decorador de classe, iterando os métodos e definindo o descritor de propriedade acima para cada um deles em uma passagem.
fonte
Necromante.
Há uma solução simples e óbvia que não requer funções de seta (as funções de seta são 30% mais lentas) ou métodos JIT por meio de getters.
Essa solução é vincular o contexto this no construtor.
Você pode escrever um método autobind para vincular automaticamente todas as funções no construtor da classe:
Observe que se você não colocar a função autobind na mesma classe que uma função membro, ela é justa
autoBind(this);
e nãothis.autoBind(this);
E também, a função autoBind acima é simplificada, para mostrar o princípio.
Se você deseja que isso funcione de forma confiável, você precisa testar se a função é um getter / setter de uma propriedade também, porque caso contrário - boom - se sua classe contém propriedades, é claro.
Como isso:
fonte
Em seu código, você tentou apenas alterar a última linha da seguinte maneira?
fonte