Perda de contexto em JavaScript
Suponha que temos uma função dentro de outra função. Vamos
chamar a função externa de parent e
a interna de child:
function parent() {
function child() {
}
}
Das lições anteriores, você sabe que se definir qualquer variável na função externa - ela estará disponível na função interna:
function parent() {
let str = 'abcde';
function child() {
console.log(str); // exibirá 'abcde'
}
child(); // chamamos a função interna
}
parent(); // chamamos a função externa
No entanto, há uma nuance: a função interna tem
acesso a todas as variáveis da função externa, mas
não tem acesso ao this. Ou seja: se
a função externa estiver vinculada a algum elemento
DOM, então this nela apontará
para esse elemento, mas o this da função
interna - não apontará!
Para onde então o this da função interna
apontará? Resposta: ele será igual a
undefined (no modo estrito), pois
a função não está vinculada a nada.
Vamos testar na prática. Suponha que temos um input:
<input id="elem" value="text">
Vamos vincular a este input a função parent,
que será chamada quando o input perder o foco:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
// Será chamada ao perder o foco:
function parent() {
// haverá algum código aqui
function child() {
// haverá algum código aqui
}
child(); // chamamos a função filha
}
Vamos exibir o conteúdo de this no
console em dois lugares: dentro da função parent
e dentro da função child:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this); // exibirá a referência ao nosso input
function child() {
console.log(this); // exibirá undefined
}
child();
}
Execute este código, faça o input perder o foco
e olhe no console - você verá que
o primeiro console.log exibirá no console
a referência ao nosso input, e o segundo - simplesmente undefined.
Esta situação, em que o this de forma inesperada
para nós não aponta para o que precisamos, é chamada de perda de contexto.
Suponha agora que em ambas as funções
iremos exibir o value do input. Determine
o que será exibido nas linhas de código marcadas com
comentários:
"use strict";
let elem = document.querySelector('#elem');
elem.addEventListener('blur', parent);
function parent() {
console.log(this.value); // o que exibirá?
function child() {
console.log(this.value); // o que exibirá?
}
child();
}