No estoy seguro del mejor enfoque para manejar el alcance de "esto" en TypeScript.
Aquí hay un ejemplo de un patrón común en el código que estoy convirtiendo a TypeScript:
class DemonstrateScopingProblems {
private status = "blah";
public run() {
alert(this.status);
}
}
var thisTest = new DemonstrateScopingProblems();
// works as expected, displays "blah":
thisTest.run();
// doesn't work; this is scoped to be the document so this.status is undefined:
$(document).ready(thisTest.run);
Ahora, podría cambiar la llamada a ...
$(document).ready(thisTest.run.bind(thisTest));
... que funciona. Pero es algo horrible. Significa que todo el código puede compilarse y funcionar bien en algunas circunstancias, pero si nos olvidamos de vincular el alcance, se romperá.
Me gustaría una forma de hacerlo dentro de la clase, de modo que cuando usemos la clase no tengamos que preocuparnos por el alcance de "esto".
¿Alguna sugerencia?
Actualizar
Otro enfoque que funciona es usar la flecha gruesa:
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
alert(this.status);
}
}
¿Es ese un enfoque válido?
typescript
this
Jonathan Moffatt
fuente
fuente
Respuestas:
Aquí tiene algunas opciones, cada una con sus propias compensaciones. Desafortunadamente, no existe una mejor solución obvia y realmente dependerá de la aplicación.
Vinculación automática de clases
Como se muestra en su pregunta:
this
contexto en lugar de que cada sitio de llamada cree un nuevo cierre al invocarlo.this
contextosuper.
Function.bind
También como se muestra:
Flecha
gruesa en TypeScript (que se muestra aquí con algunos parámetros ficticios por razones explicativas):
fuente
Otra solución que requiere una configuración inicial pero que vale la pena con su sintaxis invencible, literalmente de una palabra, es usar Decoradores de métodos para enlazar métodos JIT a través de getters.
Creé un repositorio en GitHub para mostrar una implementación de esta idea (es un poco largo para encajar en una respuesta con sus 40 líneas de código, incluidos los comentarios) , que usaría tan simplemente como:
Todavía no he visto esto mencionado en ninguna parte, pero funciona perfectamente. Además, este enfoque no tiene una desventaja notable: la implementación de este decorador, incluida la verificación de tipos para la seguridad de tipos en tiempo de ejecución , es trivial y sencilla, y tiene una sobrecarga esencialmente cero después de la llamada inicial al método.
La parte esencial es definir el siguiente getter en el prototipo de clase, que se ejecuta inmediatamente antes de la primera llamada:
Fuente completa
La idea también se puede llevar un paso más allá, haciendo esto en un decorador de clases, iterando sobre los métodos y definiendo el descriptor de propiedad anterior para cada uno de ellos en una sola pasada.
fuente
Nigromante.
Existe una solución simple y obvia que no requiere funciones de flecha (las funciones de flecha son un 30% más lentas) o métodos JIT a través de getters.
Esa solución es vincular el contexto this en el constructor.
Puede escribir un método de autobind para vincular automáticamente todas las funciones en el constructor de la clase:
Tenga en cuenta que si no coloca la función autobind en la misma clase que una función miembro, es solo
autoBind(this);
y nothis.autoBind(this);
Y también, la función autoBind anterior está simplificada, para mostrar el principio.
Si desea que esto funcione de manera confiable, debe probar si la función también es un getter / setter de una propiedad, porque de lo contrario, boom, si su clase contiene propiedades, eso es.
Me gusta esto:
fuente
En su código, ¿ha intentado simplemente cambiar la última línea de la siguiente manera?
fuente