jquery this typescript proxy-classes

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)); } }