¿Qué significa 'var that = this;' ¿Qué significa en JavaScript?
En un archivo JavaScript vi:
function Somefunction(){
var that = this;
...
}
¿ Cuál es el propósito de declararle that
y asignarle this
esto?
Voy a comenzar esta respuesta con una ilustración:
var colours = ['red', 'green', 'blue'];
document.getElementById('element').addEventListener('click', function() {
// this is a reference to the element clicked on
var that = this;
colours.forEach(function() {
// this is undefined
// that is a reference to the element clicked on
});
});
Mi respuesta originalmente demostró esto con jQuery, que es sólo ligeramente diferente:
$('#element').click(function(){
// this is a reference to the element clicked on
var that = this;
$('.elements').each(function(){
// this is a reference to the current element in the loop
// that is still a reference to the element clicked on
});
});
Debido a que this
cambia con frecuencia cuando cambia el alcance llamando a una nueva función, no puede acceder al valor original usándola. Ponerle un alias le that
permite seguir accediendo al valor original de this
.
Personalmente, no me gusta el uso de that
como alias. Rara vez es obvio a qué se refiere, especialmente si las funciones tienen más de un par de líneas. Siempre uso un alias más descriptivo. En mis ejemplos anteriores, probablemente usaría clickedEl
.
Desde Crockford
Por convención, hacemos privada esa variable. Esto se utiliza para que el objeto esté disponible para los métodos privados. Esta es una solución alternativa para un error en la especificación del lenguaje ECMAScript que hace que se configure incorrectamente para funciones internas.
JS Violín
function usesThis(name) {
this.myName = name;
function returnMe() {
return this; //scope is lost because of the inner function
}
return {
returnMe : returnMe
}
}
function usesThat(name) {
var that = this;
this.myName = name;
function returnMe() {
return that; //scope is baked in with 'that' to the "class"
}
return {
returnMe : returnMe
}
}
var usesthat = new usesThat('Dave');
var usesthis = new usesThis('John');
alert("UsesThat thinks it's called " + usesthat.returnMe().myName + '\r\n' +
"UsesThis thinks it's called " + usesthis.returnMe().myName);
Esto alerta...
UsosEso cree que se llama Dave.
UsosEsto cree que se llama indefinido.
Este es un truco para hacer que las funciones internas (funciones definidas dentro de otras funciones) funcionen mejor como deberían. En javascript, cuando define una función dentro de otra, this
automáticamente se establece en el alcance global. Esto puede resultar confuso porque espera this
tener el mismo valor que en la función externa.
var car = {};
car.starter = {};
car.start = function(){
var that = this;
// you can access car.starter inside this method with 'this'
this.starter.active = false;
var activateStarter = function(){
// 'this' now points to the global scope
// 'this.starter' is undefined, so we use 'that' instead.
that.starter.active = true;
// you could also use car.starter, but using 'that' gives
// us more consistency and flexibility
};
activateStarter();
};
Esto es específicamente un problema cuando creas una función como método de un objeto (como car.start
en el ejemplo) y luego creas una función dentro de ese método (como activateStarter
). En el método de nivel superior this
apunta al objeto, es un método de (en este caso, car
) pero en la función interna this
ahora apunta al alcance global. Esto es un dolor.
Crear una variable para usar por convención en ambos ámbitos es una solución para este problema tan general con javascript (aunque también es útil en funciones jquery). Por eso that
se utiliza el nombre que suena muy general. Es una convención fácilmente reconocible para superar una deficiencia en el idioma.
Como insinúa El Ronnoco, Douglas Crockford cree que es una buena idea.