jquery - Mecanografiar "esto" dentro de un método de clase
jquery proxy (5)
Sé que esto es probablemente dolorosamente básico, pero estoy teniendo un momento difícil para entenderlo.
class Main
{
constructor()
{
requestAnimationFrame(this.update); //fine
}
update(): void
{
requestAnimationFrame(this.update); //error, because this is window
}
}
Parece ser que necesito un proxy, así que digamos usando Jquery
class Main
{
constructor()
{
this.updateProxy = $.proxy(this.update, this);
requestAnimationFrame(this.updateProxy); //fine
}
updateProxy: () => void
update(): void
{
requestAnimationFrame(this.updateProxy); //fine
}
}
Pero viniendo de un trasfondo de Actionscript 3, no estoy realmente seguro de lo que está sucediendo aquí. Lo siento, no estoy seguro de dónde comienza Javascript y termina TypeScript.
updateProxy: () => void
Y también, no estoy convencido de que estoy haciendo esto bien. Lo último que quiero es que la mayoría de mi clase tenga una función aa () a la que se debe acceder con aProxy()
ya que creo que estoy escribiendo lo mismo dos veces. ¿Es normal?
Consulte la página 72 de la especificación del lenguaje de mecanografía https://github.com/Microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification.pdf?raw=true
Flecha Funciones Expresiones
En el ejemplo
class Messenger {
message = "Hello World";
start() {
setTimeout(() => alert(this.message), 3000);
}
};
var messenger = new Messenger();
messenger.start();
el uso de una expresión de función de flecha hace que la devolución de llamada tenga el mismo efecto que el método circundante de ''inicio''. Al escribir la devolución de llamada como una expresión de función estándar, se hace necesario organizar manualmente el acceso al entorno, por ejemplo, copiándolo en una variable local:
Este es el Javascript generado actualmente:
class Messenger {
message = "Hello World";
start() {
var _this = this;
setTimeout(function() { alert(_this.message); }, 3000);
}
};
El problema surge cuando pasas una función como una devolución de llamada. Para cuando se haya ejecutado la devolución de llamada, el valor de "esto" podría haber cambiado a la Ventana, el control que invoca la devolución de llamada, o alguna otra cosa.
Asegúrese de utilizar siempre una expresión lambda en el momento en que pasa una referencia a la función para devolverla. Por ejemplo
public addFile(file) {
this.files.push(file);
}
//Not like this
someObject.doSomething(addFile);
//but instead, like this
someObject.doSomething( (file) => addFile(file) );
Esto compila a algo como
this.addFile(file) {
this.files.push(file);
}
var _this = this;
someObject.doSomething(_this.addFile);
Como se llama a la función addFile en una referencia de objeto específica (_this), no utiliza el "this" del invocador sino el valor de _this.
En resumen, la palabra clave this siempre tiene una referencia al objeto que llamó a la función.
En Javascript, dado que las funciones son solo variables, puede pasarlas.
Ejemplo:
var x = {
localvar: 5,
test: function(){
alert(this.localvar);
}
};
x.test() // outputs 5
var y;
y.somemethod = x.test; // assign the function test from x to the ''property'' somemethod on y
y.test(); // outputs undefined, this now points to y and y has no localvar
y.localvar = "super dooper string";
y.test(); // outputs super dooper string
Cuando haces lo siguiente con jQuery:
$.proxy(this.update, this);
Lo que estás haciendo es anular ese contexto. Detrás de las escenas jQuery te guiará esto:
$.proxy = function(fnc, scope){
return function(){
return fnc.apply(scope); // apply is a method on a function that calls that function with a given this value
}
};
Si desea que this
capturado, la forma de hacerlo de TypeScript es a través de las funciones de flecha. Para citar a Anders:
El
this
en funciones de flecha tiene un alcance léxico
Esta es la forma en que me gusta utilizar esto para mi ventaja:
class test{
// Use arrow functions
func1=(arg:string)=>{
return arg+" yeah" + this.prop;
}
func2=(arg:number)=>{
return arg+10 + this.prop;
}
// some property on this
prop = 10;
}
Ver esto en el Playground de TypeScript
Puedes ver que en el JavaScript generado this
se captura fuera de la llamada a la función:
var _this = this;
this.prop = 10;
this.func1 = function (arg) {
return arg + " yeah" + _this.prop;
};
por lo tanto, this
valor dentro de la llamada a la función (que podría ser una window
) no se usaría.
Para obtener más información: "Entender this
en TypeScript" (4:05) - YouTube
Si escribe sus métodos de esta manera, ''esto'' será tratado de la manera que espera.
class Main
{
constructor()
{
requestAnimationFrame(() => this.update());
}
update(): void
{
requestAnimationFrame(() => this.update());
}
}
Otra opción sería vincular "esto" a la llamada de función:
class Main
{
constructor()
{
requestAnimationFrame(this.update.bind(this));
}
update(): void
{
requestAnimationFrame(this.update.bind(this));
}
}