Contexto Javascript – esta palavra-chave

Deepak Gupta Blocked Unblock Seguir Seguindo 6 de janeiro Foto de sydney Rae no Unsplash

O contexto é um daqueles tópicos que sempre criam muita confusão ao iniciar o aprendizado de javascript e um tópico que o entrevistador faz muito.

Vamos começar…

O que é contexto?

Contexto é sempre o valor da palavra this chave this que é uma referência ao objeto que “possui” o código atualmente em execução ou a função em que ele é examinado.

Sabemos que a window é um objeto global no navegador, por isso, se digitarmos this no console e ele deve retornar o objeto da janela, o que ele faz.

Na CLI node.js, se você tentar fazer o acima, obterá um objeto que terá todas as funções utilizadas globalmente, como console , process etc. (tente uma vez).

Nota: O valor this palavra this chave depende do objeto em que a função é executada / chamada / sit on. Portanto, this palavra-chave tem valores diferentes, dependendo de onde ela é usada.

Nota: A partir de agora, isso e o contexto são usados de forma intercambiável.

Contexto – globalmente e dentro de uma função.

isso no nível global chamado no objeto global

foo a função é definida no nível global e é chamada no objeto de nível global ie window so chamando foo e window.foo é o mesmo. Portanto, o contexto é um objeto de window .

esta função interna chamada no objeto de função em nível global

Considerando que, se fizermos o new foo() em nível global, obteremos this como objeto foo .

Nota: o new operador cria uma instância de um objeto. O contexto da função será definido para a instância criada de um objeto.

Contexto – sob a função de 2º nível

Contexto – quando a função é definida globalmente e usada sob um objeto ( Ligação implícita ).

Nota: De cima, obtemos que o valor this palavra this chave depende de a função ser chamada não onde a função está definida.

Como o contexto se comporta em 'use strict'?

Ao usar o use strict em uma função o contexto ou seja, esta palavra-chave se comporta de maneira diferente. O contexto permanece como o que foi chamado.

Nota: Todo o nosso programa deve ser strict ou non-strict . No entanto, às vezes você inclui uma biblioteca de terceiros com Strict'ness diferente do seu, portanto, é necessário ter cuidado com esses detalhes sutis de compatibilidade.

Como o contexto se comporta na função de seta?

As funções de seta funcionam de maneira diferente das funções regulares em termos de contexto. this vai referem-se sempre ao âmbito lexical ( li aqui sobre escopo ), ou seja, this mantém o valor do contexto de que encerram lexicais.

No código global, ele será definido para o objeto global, portanto, ficamos acima da verdade.

Como o contexto se comporta na cadeia de protótipos do objeto?

O contexto segue a mesma regra, ou seja, se a função estiver na cadeia de protótipos de um objeto, this se refere ao objeto em que o método foi chamado.

Se chamarmos obj.func() será undefined e se func for chamado em newObj criado a partir de obj que tem x definido, retornará o valor 10.

Como o contexto se comporta nos manipuladores de eventos?

O contexto em manipuladores de eventos de caso refere-se ao elemento que recebeu o evento.

Aqui nós adicionamos um evento jquery click na tag body do DOM, e podemos ver que o contexto retorna o elemento body.

Como o contexto se comporta no contexto de execução?

Se você não sabe o que é o contexto de execução ( leia aqui ). Em contexto de execução curta é o 'ambiente' ou escopo no qual uma função é executada. Toda vez que uma função é chamada, um novo execution context é criado. Cada chamada para um execution context tem 2 estágios

  1. Criação – quando a função é chamada
  2. Ativação – quando a função é executada

O valor this é determinado na fase de criação, não no momento da execução. No entanto, this regra de determinação permanece a mesma.

Como o contexto é diferente do escopo?

Escopo e contexto são um conceito completamente diferente, mas geralmente usados pelo próximo desenvolvedor de forma intercambiável.

O escopo é a acessibilidade de variáveis, funções ou objetos em alguma parte específica do seu código durante o tempo de execução. Leia aqui mais sobre escopos.

Cada chamada de função tem um escopo e um contexto associados a ela.

Como explicitamente alterar o contexto?

Podemos alterar dinamicamente o contexto de qualquer método usando o método call() , apply() e bind() .

Chamada – A primeira call argumento é o contexto que você deseja usar. Depois, você pode passar qualquer quantidade de valores separados por vírgulas.

 foo.call(context, param1, param2, param3 ); 

Aplicar – Isso é o mesmo que call mas difere no sentido de não. de argumento. Aplique apenas argumentos de suporte 2, contexto e matriz de valores .

 foo.apply( context,[param1, param2, param3]); 

Vincular – Retorna uma nova função que é permanentemente vinculada ao primeiro argumento de bind independentemente de como a função está sendo usada. bind não invoca a função ligada imediatamente, mas retorna uma nova função que podemos executar depois.

Por que precisamos mudar explicitamente o contexto?

  1. Quando precisamos chamar uma função definida dentro de um objeto dizer x mas em outros objetos dizem y podemos usar métodos explícitos para fazê-lo, para aumentar a capacidade de reutilização.

2. O currying e a aplicação parcial são outra parte em que a mudança explícita no contexto é usada.

3. Para fazer funções de utilidade como

4. Herança é outro lugar onde a mudança explícita de contexto pode ser usada.

Comente abaixo se você souber mais razões 🙂

Quais são os casos em que precisamos cuidar do contexto?

Podemos perder o contexto, ou seja, obter um valor undefined para this em

1. Funções Aninhadas

Precisamos manter o contexto do objeto obj referenciado para quando a função de callback é chamada, no que acima não acontece e obtemos o erro.

Podemos nos livrar do erro acima, substituindo o código exec com abaixo

 // use of bind 
exec: function () {
this.f2(function () {
this.f1();
}.bind(this));
}
 // use of arrow function 
exec: function () {
this.f2(() => {
this.f1();
});
}
 // outro caminho não recomendado embora 
exec: function () {
var that = this;
this.f2(() => {
that.f1();
});
}

2. Método como callback

 let obj = { 
name: "test",
waveHi() {
return ('Hi',this.name);
}
};

setTimeout(obj.waveHi, 1000)

O acima irá retornar Hi undefined , pense por um segundo por quê? Isso porque a última linha será

 let f = obj.waveHi; 
setTimeout(f, 1000);

e, setTimeout tem a função obj.waveHi , separada do objeto obj

Soluções são

 // Wrapping function 
setTimeout(function() {
obj.waveHi(); // Hi Test
}, 1000);
 // função de seta 
setTimeout(() => obj.waveHi(), 1000); // Hi Test
 // uso de bind 
let waveHi = obj.waveHi.bind(obj);
waveHi() // Hi Test

Nota:

1. Criar uma “referência de método vinculada” requer uma função de wrapper anônima e um custo de chamada. Em situações específicas, os fechamentos de alavancagem podem ser uma alternativa melhor.

2. Qualquer tipo de referência de função (atribuindo como um valor, passando como um argumento) perde a ligação original da função.