* Lo más probable es que me perdí algo, pero estoy seguro de que los comentarios me dirán estoEstoy escribiendo este artículo para mis necesidades personales. Está previsto que contendrá las respuestas a todas las preguntas que los estudiantes me hagan sobre este tema. Si es útil para alguien más, genial.
Contenido
- Introduccion
- Ideas erróneas sobre esto
- Cómo determinar el valor de esto
Introduccion
this
es una de las características más confusas del lenguaje JavaScript. Procedente de Java, estaba destinado a ayudar en la implementación de OOP. Escribí en Java durante algún tiempo, y debo decir que durante este tiempo, tal vez una vez dudé de lo que es igual en un lugar particular del código. En JavaScript, tales dudas pueden surgir todos los días, al menos hasta el momento en que aprende algunas reglas simples pero no obvias.
Ideas erróneas sobre this
Hay varias ideas falsas comunes con respecto a esta palabra clave. Quiero disiparlos rápidamente antes de llegar al punto.
Este es un contexto léxico.Esta impresión a menudo surge entre los principiantes. Les parece que
this
es un objeto en el que, como las propiedades, se almacenan todas las variables en este ámbito. Esta idea errónea se deriva del hecho de que en un caso particular, en términos generales, es así. Si estamos en el nivel más alto, entonces
this
es igual a la
window
(en el caso de un script normal en el navegador). Y como sabemos, todas las variables declaradas en el nivel superior están disponibles como propiedades de
window
.
En general, esto no es cierto. Esto es fácil de verificar.
function test(){ const a = " , "; console.log(this.a); } test();
este es el objeto al que pertenece el métodoNuevamente, esto es cierto en muchos casos específicos, pero no siempre. Lo importante es cómo se llama la función, y no si es una propiedad de algún objeto. Esto es comprensible incluso desde una lógica muy simple: supongamos que la misma función es una propiedad de dos objetos simultáneamente.
const f = function(){ console.log(this); } const object1 = { method: f }; const object2 = { method: f };
Entonces, ¿cuál de estos objetos será ella?
Importante! Incluso si se crea un objeto utilizando clases ES6, esto no garantiza en absoluto que su método siempre lo tenga. No se deje engañar por el parecido con las clases de idiomas "normales".
Esta es una técnica Jedi que, una vez que se aprende, debe usarse en todas partesEs mejor evitar usar
this
si es posible. El único caso cuando está completamente justificado es OOP. En otros lugares, usar
this
no solo es malo, sino que generalmente es una exageración que confunde el código. En esencia,
this
es un argumento adicional "menos el primero" para la función, que se pasa allí de una manera complicada y no obvia al principiante. Con alta probabilidad, puede ser reemplazado por el argumento habitual, y solo mejorará.
Cómo determinar el valor de esto
Aquí trataré de dar un algoritmo riguroso y conciso con el que incluso un codificador inexperto podrá comprender a qué equivale esto en su caso particular. Se esconderán explicaciones más detalladas debajo de los spoilers, para no abarrotar el espacio visual.
- ¿Estamos dentro de una función?
- Sí: ver el siguiente artículo.
- No:
this
es igual a un objeto global .
ComentarioEn el código de nivel superior (no dentro de ninguna función), this
siempre se refiere a un objeto global. En el caso de un script normal en el navegador, este es un objeto de window
. Pero en general, hay diferentes casos.
- ¿Estamos dentro de la función de flecha?
- Sí: el valor de
this
es el mismo que en la función un nivel más alto (es decir, que contiene este). Regrese al paso anterior y repita el algoritmo para ello. Si la función no está contenida en ningún otro, this
es un objeto global. - No: ver el siguiente párrafo.
ComentarioUna de las principales características de las funciones de flecha es el llamado " this
léxico". Esto significa que el valor de this
en la función de flecha está determinado únicamente por dónde (en qué contexto léxico) se creó, y no depende de cómo se llamó posteriormente. A veces esto no es lo que necesitamos, pero con mayor frecuencia hace que las funciones de flecha sean muy convenientes y predecibles.
- ¿Se llama esta función como constructor (usando el nuevo operador)?
- Sí:
this
refiere a un nuevo objeto que está "en construcción". - No: ver el siguiente párrafo.
ComentarioQuizás valga la pena especificar por separado el caso cuando se trata del constructor de la clase ES6 heredada. Luego, antes de llamar a super()
, this
no tiene un valor (el acceso provocará un error), y después de llamar a super()
es igual al nuevo objeto de la clase padre.
- ¿Esta función se crea usando el enlace ?
- Sí: el valor de
this
es igual al valor del primer argumento que pasamos al método de bind
al crear esta función. - No: ver el siguiente párrafo.
ComentarioEl método de bind
crea una copia de la función, corrigiendo this
y, opcionalmente, los primeros argumentos para ello. De hecho, esto crea no solo una copia de la función, sino, cito, un "objeto BoundFunction exótico". Su exotismo se manifiesta, en particular, en que por un llamado repetido a bind
ya no podemos cambiar this
. Por lo tanto, estrictamente hablando, la respuesta en este párrafo debe formularse de la siguiente manera: si es así, entonces this
es igual al primer argumento de la primera llamada a bind
, que condujo a la creación de esta función.
- ¿Esta función se pasa a alguna parte como devolución de llamada o manejador?
- Sí: solo el Señor sabe lo que esto igualará cuando sea convocado. Ve a leer la documentación de lo que lo causará.
- No: ver el siguiente párrafo.
ComentarioPara una función enlazada y sin flecha, el valor de
this
depende de las circunstancias en las que se llamó. Si no lo llama personalmente, pero lo pasa a algún lado, entonces
this
valor puede ser sustituido o no por un valor desconocido para usted.
Ejemplos:
`use strict` document.addEventListener('keydown', function(){ console.log(this); });
- Esta función se llama mediante el uso o la llamada ?
- Sí: en este caso,
this
equivale al primer argumento pasado al método correspondiente. - No: ver el siguiente párrafo.
ComentarioOtra forma de establecer this
explícitamente. Más precisamente, dos. Sin embargo, en términos de this
hay diferencia entre apply
y call
, la única diferencia es cómo se pasan el resto de los argumentos.
- ¿Se obtiene esta función como el valor de una propiedad de objeto y se llama inmediatamente?
- Sí:
this
es igual al objeto anterior. - No: ver el siguiente párrafo.
ComentarioEn realidad, a partir de este mecanismo (así como de la experiencia de trabajar con otros idiomas) crecen las piernas de la creencia de que "
this
es el objeto cuyo método llamamos". Quizás solo escriba el código.
'use strict'; const object1 = { method: function(){ console.log(this); } } const object2 = { method: object1.method } object1.method();
- ¿El código se ejecuta en modo estricto? ('uso estricto', módulo ES6)
- Sí:
this
es igual a undefined
. - No:
this
es igual a un objeto global.
ComentarioSi llegamos a este punto, entonces
this
no
this
establecido por ninguno de los mecanismos que permiten que se establezca. Hay varios conceptos erróneos sobre cómo se puede pasar esto. Por ejemplo, durante las entrevistas a menudo me dicen tal cosa:
const obj = { test: function(){ (function(){ console.log(this); })();
O, como dije en la sección de "conceptos erróneos", muchas personas piensan que si una función es un método de un objeto creado usando clases ES6, entonces esto siempre será igual a este objeto en él. Esto tampoco es cierto.
Entonces, si llegamos a este punto, las otras circunstancias de llamar a nuestra función no importan. Y todo se reduce a si estamos en modo estricto o no.
Históricamente, como "predeterminado"
this
, se pasó un objeto global a tales funciones. Este enfoque fue luego reconocido como inseguro. ES5 introdujo un modo estricto que corrige muchos problemas de versiones anteriores de ECMAScript. Se incluye con la directiva 'use estricto' al comienzo de un archivo o función. En este modo, el valor "predeterminado" de
this
undefined
está
undefined
.
En los módulos ES6, el modo estricto está habilitado de forma predeterminada.
También hay otros mecanismos para incluir el modo estricto, por ejemplo, en NodeJS, el modo estricto para todos los archivos se puede habilitar con el
--use-strict
.
Eso, en general, es todo. Determinar el valor de
this
, por supuesto, es menos simple de lo que nos gustaría, pero no es tan difícil como parece. Aprenda este algoritmo como una tabla de multiplicar, y nunca más tendrá problemas con
this
. Tales cosas
El usuario de PS
Aingis sugirió que cuando se usa la construcción
with , el objeto que se le pasa como contexto reemplaza al objeto global. Quizás no ingresaré esto en mi clasificador, porque la posibilidad de reunirme en 2019+ es bastante pequeña. Pero en cualquier caso, este es un punto interesante.
El usuario de PPS
rqrqrqrq sugirió que
new
mayor prioridad que
bind
. La revisión correspondiente al clasificador ya se ha realizado. Gracias