JavaScript es un lenguaje de paradigmas múltiples que admite programación orientada a objetos y enlace dinámico de métodos, un concepto poderoso que permite que la estructura del código JavaScript cambie durante la ejecución del programa. Esto brinda a los desarrolladores oportunidades serias, hace que el lenguaje sea flexible, pero hay que pagar por todo. En este caso, debe pagar con la comprensión del código. La
this
hace una contribución significativa a este precio, en torno al comportamiento del cual se han recopilado muchas cosas que pueden confundir al programador.

Enlace de método dinámico
El enlace dinámico le permite especificar, durante la ejecución del programa, y no durante la compilación, el método que debe llamarse al ejecutar un comando determinado. En JavaScript, este mecanismo se implementa utilizando la
this
y la cadena de prototipos. En particular, el valor específico de
this
dentro del método se determina en tiempo de ejecución, y las reglas para determinar este valor varían dependiendo de cómo se declaró el método.
Juguemos un juego. Lo llamo "¿Qué está escrito en esto?". Aquí está su primera opción: código del módulo ES6:
const a = { a: 'a' }; const obj = { getThis: () => this, getThis2 () { return this; } }; obj.getThis3 = obj.getThis.bind(obj); obj.getThis4 = obj.getThis2.bind(obj); const answers = [ obj.getThis(), obj.getThis.call(a), obj.getThis2(), obj.getThis2.call(a), obj.getThis3(), obj.getThis3.call(a), obj.getThis4(), obj.getThis4.call(a) ];
Antes de seguir leyendo, piense en lo que caerá en la matriz de respuestas y escriba las respuestas. Después de hacer esto, pruébelo
answers
matriz de
answers
usando
console.log()
. ¿Se las arregló para "descifrar" correctamente el valor de
this
en cada uno de los casos?
Analizaremos este problema, comenzando con el primer ejemplo. La construcción
obj.getThis()
devuelve
undefined
. Por qué Esta función de flecha no puede vincularse. Dichas funciones usan
this
desde su alcance léxico circundante. El método se llama en el módulo ES6, en su ámbito léxico
this
no estará
undefined
. Por la misma razón,
undefined
devolverá una llamada a
obj.getThis.call(a)
. El valor de
this
cuando se trabaja con funciones de flecha no se puede reasignar incluso con
.call()
o
.bind()
. Este valor siempre corresponderá a
this
desde el ámbito léxico, en el que se encuentran dichas funciones.
El
obj.getThis2()
muestra cómo trabajar con
this
cuando se utilizan métodos de objeto normales. Si
this
no
this
vinculado a un método similar, y siempre que este método no sea una función de flecha, es decir, que admita
this
enlace,
this
palabra clave está vinculada al objeto para el que se llama al método utilizando la sintaxis de acceso a las propiedades del objeto a través de punto o usando corchetes.
La
obj.getThis2.call(a)
ya es un poco más difícil de entender. El método
call()
permite llamar a una función con un valor dado de
this
, que se indica como un argumento opcional. En otras palabras, en este caso,
this
se toma del parámetro
.call()
, como resultado, la llamada a
obj.getThis2.call(a)
devuelve el objeto
a
.
Usando el comando
obj.getThis3 = obj.getThis.bind(obj);
Estamos intentando vincularnos a
this
método, que es una función de flecha. Como ya hemos descubierto, esto no se puede hacer. Como resultado, las llamadas a
obj.getThis3()
y
obj.getThis3.call(a)
devuelven
undefined
.
Los métodos que son funciones ordinarias se pueden unir a
this
, por lo que
obj.getThis4()
, como se esperaba, devuelve
obj
. Una llamada a
obj.getThis4.call(a)
devuelve
obj
y no, como es de esperar,
a
. El hecho es que, antes de llamar a este comando, ya lo
obj.getThis4 = obj.getThis2.bind(obj);
con el
obj.getThis4 = obj.getThis2.bind(obj);
. Como resultado, al ejecutar
obj.getThis4.call(a)
, se tiene en cuenta el estado del método en el que se encontraba después del primer enlace.
Usando esto en clases
Aquí está la segunda versión de nuestro juego, la misma tarea, pero ahora basada en clases. Aquí usamos la sintaxis para declarar campos de clase pública (en este momento, la
propuesta para esta sintaxis se encuentra en la tercera etapa de aprobación, está disponible de forma predeterminada en Chrome, puede usarla con
@babel/plugin-proposal-class-properties
).
class Obj { getThis = () => this getThis2 () { return this; } } const obj2 = new Obj(); obj2.getThis3 = obj2.getThis.bind(obj2); obj2.getThis4 = obj2.getThis2.bind(obj2); const answers2 = [ obj2.getThis(), obj2.getThis.call(a), obj2.getThis2(), obj2.getThis2.call(a), obj2.getThis3(), obj2.getThis3.call(a), obj2.getThis4(), obj2.getThis4.call(a) ];
Antes de seguir leyendo, piense en el código y escriba su visión de lo que caerá en la matriz de
answers2
.
¿Ya terminaste?
Aquí, todas las llamadas a métodos, excepto
obj2.getThis2.call(a)
, devolverán una referencia a la instancia del objeto. La misma llamada devolverá el objeto
a
. Las funciones de flecha todavía toman
this
del ámbito léxico. La diferencia entre este ejemplo y el anterior es la diferencia en el alcance del que se toma esto.
A saber, aquí trabajamos con propiedades de clase, que determina el comportamiento de este código.
El hecho es que durante la preparación del código para la ejecución, los valores se escriben en las propiedades de las clases de esta manera:
class Obj { constructor() { this.getThis = () => this; } ...
En otras palabras, resulta que la función de flecha se declara dentro del contexto de la función constructora. Dado que estamos trabajando con una clase, la única forma de crear una instancia es usar la
new
palabra clave (si olvida esta palabra clave, se mostrará un mensaje de error).
Las tareas más importantes resueltas por la
new
palabra clave son crear una nueva instancia del objeto y vincular
this
al constructor. Esta característica, teniendo en cuenta lo que ya mencionamos en la sección anterior, debería ayudarlo a comprender lo que está sucediendo.
Resumen
¿Has completado las tareas descritas en este artículo? Una buena comprensión de cómo se comporta
this
palabra clave en JavaScript le ahorrará un montón de tiempo al depurar, al buscar razones no obvias para errores oscuros. Si respondió algunas de las preguntas de manera incorrecta, significa que le será útil practicar.
Experimente con el código de muestra, y luego inténtelo nuevamente, y así sucesivamente, hasta que pueda responder todas las preguntas correctamente. Después de resolverlo usted mismo, encuentre a alguien listo para escucharlo y dígale por qué los métodos de las tareas devuelven exactamente lo que devuelven.
Si todo esto le parece más complicado de lo que esperaba, entonces sepa que no está solo en esto. Probé un buen número de desarrolladores para conocer las características de
this
, y creo que solo uno de ellos fue absolutamente exacto en todas sus respuestas.
Ese subsistema del lenguaje, que al principio parecía una búsqueda dinámica de métodos que podrían ser influenciados usando
.call()
,
.bind()
o
.apply()
, comenzó a parecer mucho más complicado después de la aparición de funciones y clases de flecha.
Aparentemente, será útil observar las características principales de las clases y las funciones de flecha en términos de uso de
this
. Recuerde que las funciones de flecha siempre usan
this
desde su alcance léxico, y la
this
en clases está, de hecho, vinculada a la función constructora de la clase. Y si alguna vez siente que no sabe exactamente qué significa
this
, use el depurador para verificar sus suposiciones al respecto.
Además, recuerde que puede hacer mucho en JavaScript sin usar
this
en su código. La experiencia me dice que casi cualquier código JS se puede reescribir en forma de funciones puras que aceptan todos los argumentos con los que trabajan, en forma de una lista de parámetros explícitamente especificada (
this
puede interpretarse como un parámetro especificado implícitamente con un estado mutable). La lógica contenida en las funciones puras es determinista, lo que mejora su capacidad de prueba. Dichas funciones no tienen efectos secundarios, lo que significa que al trabajar con ellas, a diferencia de manipular
this
, es poco probable que "rompa" algo fuera de él. Cada vez que cambia
this
, se enfrenta a un problema potencial, que es que algo que depende de
this
puede dejar de funcionar correctamente.
A pesar de lo anterior, debe tenerse en cuenta que
this
es un concepto útil. Por ejemplo, se puede aplicar para organizar el intercambio de un determinado método por una multitud de objetos. Incluso en la programación funcional,
this
puede ser útil para llamar a otros métodos desde un método de un objeto, lo que le permite crear algo nuevo basado en construcciones existentes.

