En TypeScript, para los métodos dentro de una clase, el tipo de this por defecto es la instancia actual de la clase. Sin embargo, si se definen los métodos como funciones flecha, el contexto de this estará ligado al momento de la declaración, no al de la invocación.
Método normal:
class Counter { value = 0; increment() { this.value++; } }
Función flecha:
class Counter { value = 0; increment = () => { this.value++; } }
Particularidades:
this cuando se pasan como callbacks (por ejemplo, en listeners de eventos).this en la firma del método para una verificación adicional:class Foo { bar(this: Foo) { // ... } }
¿Cuál es la diferencia entre
increment()yincrement = () => {}en una clase? ¿Cómo afecta esto al contexto dethiscuando se usa como callback?
Respuesta incorrecta:
Respuesta correcta:
this se define en el momento de la invocación. Si se pasa el método como función: setTimeout(counter.increment, 0), entonces this será undefined (en modo estricto) o window (en modo no estricto), mientras que la función flecha mantendrá su entorno:class Demo { value = 1; inc() { console.log(this.value); } incArrow = () => { console.log(this.value); } } const d = new Demo(); setTimeout(d.inc, 0); // undefined o error setTimeout(d.incArrow, 0); // 1
Historia
En un proyecto con frameworks reactivos, se pasaron los métodos de clase directamente como callbacks sin un bind explícito. Como resultado, this se volvió undefined, y la aplicación fallaba con un error al acceder a las propiedades de this. Se resolvió el problema reescribiendo los métodos como funciones flecha o usando un bind explícito.
Historia
Un desarrollador especificó explícitamente el tipo de this en el método, pero olvidó la tipificación dentro de la función flecha dentro de ese método. Como resultado, this dentro del callback anidado no apuntaba a la instancia de la clase, sino a window. El equipo se enfrentó a una fuga de estado, y se tuvo que rehacer la arquitectura de eventos.
Historia
Un gran componente de UI ralentizaba la aplicación, porque todos los métodos se habían descrito como campos flecha de la clase (new Counter().increment = ...), lo que creaba nuevas copias de funciones para cada instancia, en lugar de una única definición en el prototipo, como sucede con el método normal. Como resultado, aumentó el consumo de memoria y se necesitó una optimización.