Me he dado cuenta de que no parece haber una explicación clara de qué es la this
palabra clave y cómo se usa correcta (e incorrectamente) en JavaScript en el sitio de Stack Overflow.
He sido testigo de un comportamiento muy extraño con él y no he podido entender por qué ha ocurrido.
¿Cómo this
funciona y cuándo debe usarse?
javascript
this
Maxim Gershkovich
fuente
fuente
this
peter.michaux.ca/articles/javascript-widgets-without-thisthis
palabra clave: rainsoft.io/gentle-explanation-of-this-in-javascriptRespuestas:
Recomiendo leer primero el artículo Alcance en JavaScript ( espejo ) de Mike West . Es una excelente y amigable introducción a los conceptos de
this
y cadenas de alcance en JavaScript.Una vez que empiezas a acostumbrarte
this
, las reglas son bastante simples. El estándar ECMAScript 5.1 definethis
:ThisBinding es algo que el intérprete de JavaScript mantiene al evaluar el código de JavaScript, como un registro de CPU especial que contiene una referencia a un objeto. El intérprete actualiza ThisBinding cada vez que establece un contexto de ejecución en uno de los tres casos diferentes:
1. Contexto de ejecución global inicial
Este es el caso del código JavaScript que se evalúa en el nivel superior, por ejemplo, cuando está directamente dentro de un
<script>
:Al evaluar el código en el contexto de ejecución global inicial, ThisBinding se establece en el objeto global
window
( §10.4.1.1 ).Introducir código de evaluación
... por una llamada directa a
eval()
ThisBinding no se modifica; es el mismo valor que el ThisBinding del contexto de ejecución de la llamada ( §10.4.2 (2) (a)).… Si no es por una llamada directa a
eval()
ThisBinding se establece en el objeto global como si se ejecutara en el contexto de ejecución global inicial ( §10.4.2 (1)).
§15.1.2.1.1 define para qué es una llamada directa
eval()
. Básicamente,eval(...)
es una llamada directa, mientras que algo como(0, eval)(...)
ovar indirectEval = eval; indirectEval(...);
es una llamada indirectaeval()
. ¿Ve la respuesta de chuckj a (1, eval) ('this') vs eval ('this') en JavaScript? y ECMA-262-5 de Dmitry Soshnikov en detalle. Capítulo 2. Modo estricto. para cuando podría usar unaeval()
llamada indirecta .Introducir código de función
Esto ocurre cuando se llama a una función. Si se llama a una función en un objeto, como in
obj.myMethod()
o el equivalenteobj["myMethod"]()
, ThisBinding se establece en el objeto (obj
en el ejemplo; §13.2.1 ). En la mayoría de los otros casos, ThisBinding se establece en el objeto global ( §10.4.3 ).La razón para escribir "en la mayoría de los otros casos" es porque hay ocho funciones integradas de ECMAScript 5 que permiten especificar ThisBinding en la lista de argumentos. Estas funciones especiales toman un llamado
thisArg
que se convierte en ThisBinding cuando se llama a la función ( §10.4.3 ).Estas funciones incorporadas especiales son:
Function.prototype.apply( thisArg, argArray )
Function.prototype.call( thisArg [ , arg1 [ , arg2, ... ] ] )
Function.prototype.bind( thisArg [ , arg1 [ , arg2, ... ] ] )
Array.prototype.every( callbackfn [ , thisArg ] )
Array.prototype.some( callbackfn [ , thisArg ] )
Array.prototype.forEach( callbackfn [ , thisArg ] )
Array.prototype.map( callbackfn [ , thisArg ] )
Array.prototype.filter( callbackfn [ , thisArg ] )
En el caso de las
Function.prototype
funciones, se invocan en un objeto de función, pero en lugar de establecer ThisBinding en el objeto de función, ThisBinding se establece enthisArg
.En el caso de las
Array.prototype
funciones, lo dadocallbackfn
se llama en un contexto de ejecución donde ThisBinding se establecethisArg
si se proporciona; de lo contrario, al objeto global.Esas son las reglas para JavaScript simple. Cuando comience a usar las bibliotecas de JavaScript (por ejemplo, jQuery), puede encontrar que ciertas funciones de la biblioteca manipulan el valor de
this
. Los desarrolladores de esas bibliotecas de JavaScript hacen esto porque tiende a admitir los casos de uso más comunes, y los usuarios de la biblioteca generalmente consideran que este comportamiento es más conveniente. Al pasar funciones de devolución de llamada que hacen referenciathis
a funciones de biblioteca, debe consultar la documentación para ver las garantías sobre cuál es el valor dethis
cuando se llama a la función.Si se pregunta cómo una biblioteca de JavaScript manipula el valor de
this
, la biblioteca simplemente está utilizando una de las funciones de JavaScript incorporadas que aceptan athisArg
. Usted también puede escribir su propia función tomando una función de devolución de llamada ythisArg
:Hay un caso especial que aún no mencioné. Al construir un nuevo objeto a través del
new
operador, el intérprete de JavaScript crea un nuevo objeto vacío, establece algunas propiedades internas y luego llama a la función de constructor en el nuevo objeto. Por lo tanto, cuando se llama a una función en un contexto de constructor, el valor dethis
es el nuevo objeto que creó el intérprete:Funciones de flecha
Las funciones de flecha (introducidas en ECMA6) alteran el alcance de
this
. Vea la pregunta canónica existente, Función de flecha vs declaración / expresiones de función: ¿Son equivalentes / intercambiables? para más información. Pero en resumen:Solo por diversión, pruebe su comprensión con algunos ejemplos
Para revelar las respuestas, pase el mouse sobre los cuadros grises claros.
¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?¿Cuál es el valor de
this
en la línea marcada cuandoobj.staticFunction()
se ejecuta? ¿Por qué?¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?¿Cuál es el valor de
this
en la línea marcada? ¿Por qué?fuente
setTimeout
ejemplo tiene unathis
dewindow(global)
.La
this
palabra clave se comporta de manera diferente en JavaScript en comparación con otros idiomas. En lenguajes orientados a objetos, lathis
palabra clave se refiere a la instancia actual de la clase. En JavaScript, el valor dethis
está determinado por el contexto de invocación de function (context.function()
) y dónde se llama.1. Cuando se usa en contexto global
Cuando se usa
this
en contexto global, está vinculado al objeto global (window
en el navegador)Cuando se usa
this
dentro de una función definida en el contexto global,this
todavía está vinculada al objeto global, ya que la función se convierte en un método de contexto global.Arriba
f1
se hace un método de objeto global. Por lo tanto, también podemos llamarlo en elwindow
objeto de la siguiente manera:2. Cuando se usa dentro del método de objeto
Cuando utiliza una
this
palabra clave dentro de un método de objeto,this
está vinculado al objeto que encierra "inmediato".Arriba he puesto la palabra inmediata entre comillas dobles. Es para señalar que si anida el objeto dentro de otro objeto, entonces
this
está vinculado al padre inmediato.Incluso si agrega la función explícitamente al objeto como método, sigue las reglas anteriores, es decir,
this
apunta al objeto primario inmediato.3. Al invocar la función sin contexto
Cuando utiliza
this
una función interna que se invoca sin ningún contexto (es decir, no en ningún objeto), está vinculada al objeto global (window
en el navegador) (incluso si la función está definida dentro del objeto).Probándolo todo con funciones
También podemos probar los puntos anteriores con funciones. Sin embargo, hay algunas diferencias.
this
. para especificarlos.new
operador.A continuación probé todas las cosas que hicimos con Object y
this
superiores, pero primero creé la función en lugar de escribir directamente un objeto.4. Cuando se usa dentro de la función constructora .
Cuando la función se usa como un constructor (es decir, cuando se llama con una
new
palabra clave), elthis
cuerpo interno de la función apunta al nuevo objeto que se está construyendo.5. Cuando se usa dentro de la función definida en la cadena del prototipo
Si el método está en la cadena de prototipo de un objeto,
this
dentro de dicho método se hace referencia al objeto en el que se llamó al método, como si el método estuviera definido en el objeto.6. Dentro de las funciones call (), apply () y bind ()
Function.prototype
.this
que se utilizará mientras se ejecuta la función. También toman cualquier parámetro para pasar a la función original cuando se invoca.fun.apply(obj1 [, argsArray])
Se estableceobj1
como el valor dethis
insidefun()
y llama a losfun()
elementos que pasanargsArray
como sus argumentos.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Estableceobj1
como el valor dethis
insidefun()
y llama afun()
pasararg1, arg2, arg3, ...
como sus argumentos.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])
- Devuelve la referencia a la funciónfun
conthis
diversión interna vinculada aobj1
y parámetrosfun
vinculados a los parámetros especificadosarg1, arg2, arg3,...
.apply
,call
ybind
debe haberse hecho evidente.apply
permite especificar los argumentos para funcionar como un objeto tipo matriz, es decir, un objeto con unalength
propiedad numérica y propiedades enteras no negativas correspondientes. Mientras quecall
permite especificar los argumentos de la función directamente. Ambosapply
ecall
inmediatamente invocan la función en el contexto especificado y con los argumentos especificados. Por otro lado,bind
simplemente devuelve la función vinculada althis
valor especificado y los argumentos. Podemos capturar la referencia a esta función devuelta asignándola a una variable y luego podemos llamarla en cualquier momento.7.
this
controladores de eventos internosthis
función de manejo de eventos directamente dentro se refiere al elemento correspondiente. Dicha asignación directa de funciones se puede hacer utilizando eladdeventListener
método o mediante los métodos tradicionales de registro de eventos comoonclick
.this
directamente dentro de la propiedad de evento (like<button onclick="...this..." >
) del elemento, se refiere al elemento.this
indirecto a través de la otra función llamada dentro de la función de manejo de eventos o propiedad de evento se resuelve en el objeto globalwindow
.attachEvent
. En lugar de asignar la función al controlador de eventos (y al hacer así el método de función del elemento), llama a la función en el evento (efectivamente lo llama en contexto global).Recomiendo probar esto mejor en JSFiddle .
8.
this
en la función de flecha ES6En una función de flecha,
this
se comportará como variables comunes: se heredará de su ámbito léxico. Las funcionesthis
, donde se define la función de flecha, serán las funciones de flechathis
.Entonces, ese es el mismo comportamiento que:
Ver el siguiente código:
fuente
this
la llamada no establece el valor de . Como el código no está en modo estricto, el valor dethis
siempre debe ser un objeto, por lo que el valor predeterminado es el objeto global. Y, de hecho, por eso pensé que podíamos hacer una llamada directamentewindow.f1()
, de modo que los mediosf1()
ya están unidos alwindow
objeto, quiero decir antes de la invocación. ¿Me estoy equivocando?window.fn
, lo que no es. el valor predeterminado es el objeto global porque no se usó ninguna referencia base en la llamada, no por el lugar donde se define la función (por lo tanto, esto todavía se establece por cómo se llamó la función). Si lo llama explícitamente usandowindow.fn
, entonces está configurando esto como ventana . El mismo resultado, una forma diferente de hacerlo. :-)Javascript
this
Invocación de funciones simples
Considere la siguiente función:
Tenga en cuenta que estamos ejecutando esto en el modo normal, es decir, no se utiliza el modo estricto.
Cuando se ejecuta en un navegador, el valor de
this
se registraría comowindow
. Esto se debe a quewindow
es la variable global en el alcance de un navegador web.Si ejecuta este mismo código en un entorno como node.js,
this
se referiría a la variable global en su aplicación.Ahora, si ejecutamos esto en modo estricto agregando la declaración
"use strict";
al comienzo de la declaración de función,this
ya no se referiría a la variable global en ninguno de los entornos. Esto se hace para evitar confusiones en modo estricto.this
sería, en este caso, simplemente iniciar sesiónundefined
, porque eso es lo que es, no está definido.En los siguientes casos, veríamos cómo manipular el valor de
this
.Llamar a una función en un objeto
Hay maneras diferentes de hacer esto. Si ha llamado a métodos nativos en Javascript como
forEach
yslice
, ya debería saber que lathis
variable en ese caso se refiere a la funciónObject
sobre la que llamó a esa función (tenga en cuenta que en javascript, casi todo es anObject
, incluidosArray
syFunction
s). Tome el siguiente código por ejemplo.Si un
Object
contiene una propiedad que contiene unFunction
, la propiedad se llama un método. Este método, cuando se llama, siempre tendrá suthis
variable configurada con laObject
que está asociada. Esto es cierto para los modos estrictos y no estrictos.Tenga en cuenta que si un método se almacena (o mejor dicho, se copia) en otra variable, la referencia a
this
ya no se conserva en la nueva variable. Por ejemplo:Considerando un escenario más comúnmente práctico:
La
new
palabra claveConsidere una función constructora en Javascript:
¿Como funciona esto? Bueno, veamos qué sucede cuando usamos la
new
palabra clave.new
palabra clave inmediatamente inicializaría unObject
tipoPerson
.Object
tiene su constructor establecido enPerson
. Además, tenga en cuenta que solotypeof awal
volveríaObject
.Object
se le asignaría el prototipo dePerson.prototype
. Esto significa que cualquier método o propiedad en elPerson
prototipo estaría disponible para todas las instancias dePerson
, inclusoawal
.Person
misma ahora se invoca;this
siendo una referencia al objeto recién construidoawal
.Bastante sencillo, ¿eh?
Tenga en cuenta que la especificación oficial de ECMAScript en ninguna parte establece que tales tipos de funciones son
constructor
funciones reales . Son funciones normales ynew
se pueden usar en cualquier función. Es solo que los usamos como tales, por lo que los llamamos solo como tales.Funciones de llamada en funciones:
call
yapply
Entonces sí, dado que los
function
s también sonObjects
(y de hecho variables de primera clase en Javascript), incluso las funciones tienen métodos que son ... bueno, funciones en sí mismas.Todas las funciones heredan de lo global
Function
, y dos de sus muchos métodos soncall
yapply
, y ambos pueden usarse para manipular el valor dethis
en la función en la que se llaman.Este es un ejemplo típico de uso
call
. Básicamente toma el primer parámetro y establecethis
la funciónfoo
como referenciathisArg
. Todos los demás parámetros pasadoscall
se pasan a la funciónfoo
como argumentos.Entonces, el código anterior iniciará sesión
{myObj: "is cool"}, [1, 2, 3]
en la consola. Muy buena manera de cambiar el valor dethis
en cualquier función.apply
es casi lo mismo quecall
aceptar que solo toma dos parámetros:thisArg
y una matriz que contiene los argumentos que se pasarán a la función. Entonces, lacall
llamada anterior se puede traducir deapply
esta manera:Tenga en cuenta que
call
yapply
puede anular el valor de lathis
invocación del método set by dot que discutimos en la segunda viñeta. Suficientemente simple :)Presentando ...
bind
!bind
es hermano decall
yapply
. También es un método heredado por todas las funciones delFunction
constructor global en Javascript. La diferencia entrebind
ecall
/apply
es que tantocall
yapply
en realidad se invoca la función.bind
, por otro lado, devuelve una nueva función con elthisArg
yarguments
preestablecido. Tomemos un ejemplo para comprender mejor esto:¿Ves la diferencia entre los tres? Es sutil, pero se usan de manera diferente. Me gusta
call
yapply
,bind
también anulará el valor dethis
establecer por invocación de método de punto.También tenga en cuenta que ninguna de estas tres funciones cambia la función original.
call
yapply
devolvería el valor de las funciones recién construidas, mientrasbind
que devolverá la función recién construida, lista para ser llamada.Cosas extra, copia esto
A veces, no le gusta el hecho de que
this
cambie con el alcance, especialmente el alcance anidado. Eche un vistazo al siguiente ejemplo.En el código anterior, vemos que el valor de
this
cambió con el alcance anidado, pero queríamos el valor delthis
alcance original. Así que 'copiado'this
athat
y utilizamos la copia en lugar dethis
. Inteligente, ¿eh?Índice:
this
por defecto?new
palabra clave?this
concall
yapply
?bind
.this
para resolver problemas de alcance anidado.fuente
"esto" tiene que ver con el alcance. Cada función tiene su propio alcance, y dado que todo en JS es un objeto, incluso una función puede almacenar algunos valores en sí misma usando "esto". OOP 101 enseña que "esto" solo es aplicable a instancias de un objeto. Por lo tanto, cada vez que se ejecuta una función, una nueva "instancia" de esa función tiene un nuevo significado de "esto".
La mayoría de las personas se confunden cuando intentan usar "esto" dentro de funciones de cierre anónimas como:
Así que aquí, dentro de cada (), "esto" no contiene el "valor" que espera (de
sobre eso). Entonces, para superar este problema (sin juego de palabras), un desarrollador podría:Pruébalo; le comenzará a gustar este patrón de programación
fuente
this
palabra clave no tiene nada que ver con el alcance. Además, tiene un significado también en funciones que no son propiedades de los objetos.this
No es TODO sobre el alcance. Se trata TODO sobre el contexto de ejecución, que no es lo mismo que el alcance. JavaScript tiene un alcance léxico (lo que significa que el alcance está determinado por la ubicación del código), perothis
está determinado por cómo se invoca la función que lo contiene, no dónde está esa función.Dado que este hilo ha aumentado, he compilado algunos puntos para lectores nuevos en el
this
tema.¿Cómo se
this
determina el valor de ?Utilizamos esta similar a la forma en que usamos los pronombres en las lenguas naturales como el Inglés: “Juan está ejecutando rápido porque él está tratando de coger el tren.” En cambio, podríamos haber escrito "... John está tratando de tomar el tren".
this
no se le asigna un valor hasta que un objeto invoca la función donde está definido. En el ámbito global, todas las variables y funciones globales se definen en elwindow
objeto. Por lo tanto,this
en una función global se refiere (y tiene el valor de) elwindow
objeto global .Cuando
use strict
,this
en funciones globales y anónimas que no están vinculadas a ningún objeto tiene un valor deundefined
.La
this
palabra clave se malinterpreta más cuando: 1) tomamos prestado un método que usathis
, 2) asignamos un método que usathis
a una variable, 3) una función que usathis
se pasa como una función de devolución de llamada y 4)this
se usa dentro de un cierre - Una función interna. (2)Lo que depara el futuro
Definido en ECMA Script 6 , las funciones de flecha adoptan el
this
enlace desde el ámbito de cierre (función o global).Si bien las funciones de flecha proporcionan una alternativa al uso
bind()
, es importante tener en cuenta que esencialmente están desactivando elthis
mecanismo tradicional en favor de un alcance léxico más ampliamente entendido. (1)Referencias
fuente
this
en JavaScript siempre se refiere al 'propietario' de la función que se está ejecutando .Si no se define un propietario explícito, se hace referencia al propietario más superior, el objeto de ventana.
Entonces si lo hiciera
element.onclick = someKindOfFunction;
this
se referiría al elemento objeto. Pero tenga cuidado, mucha gente comete este error.<element onclick="someKindOfFunction()">
En el último caso, simplemente hace referencia a la función, no la entrega al elemento. Por lo tanto,
this
se referirá al objeto de la ventana.fuente
Cada contexto de ejecución de Javascript tiene un presente que tendrá el parámetro por:
eval
Puede establecer el valor de esto usando
func.call
,func.apply
ofunc.bind
.Por defecto, y lo que confunde a la mayoría de los principiantes, cuando se llama a un oyente después de que se genera un evento en un elemento DOM, este valor de la función es el elemento DOM.
jQuery hace que este cambio sea trivial con jQuery.proxy.
fuente
this
en Javascript es que es no una propiedad intrínseca de la función en sí, sino más bien un artefacto de la forma en que se invoca la función.func.call
,func.bind
etc. - Sushilthis
no no hacer referencia ámbito de una función.this
hará referencia a un objeto específico (o posiblementeundefined
), que como has dicho se puede cambiar usando.call()
o.apply()
. El alcance de una función es (esencialmente, cuando se simplifica) a qué variables tiene acceso, y esto depende completamente de dónde se declara la función y no se puede cambiar.this
y el alcance no tiene nada que ver entre sí en ES5 y antes (por ejemplo, cuando se escribió esta respuesta). En ES2015 (también conocido como ES6),this
y el alcance se relacionan de una manera bastante mínima con las funciones de flecha wrt (la funciónthis
en una flecha se hereda de su alcance adjunto), perothis
nunca se refiere a un alcance.Aquí es una buena fuente de
this
enJavaScript
.Aquí está el resumen:
global esto
En un navegador, en el ámbito global,
this
es elwindow
objetoAl
node
usar la respuesta,this
es el espacio de nombres superior. Puedes referirte a él comoglobal
.Al
node
ejecutar desde un script,this
en el ámbito global comienza como un objeto vacío. No es lo mismo queglobal
funciona esto
Excepto en el caso de los controladores de eventos DOM o cuando
thisArg
se proporciona un (ver más abajo), tanto en el nodo como en un navegador utilizandothis
una función que no se llama connew
referencias al alcance global ...Si usa
use strict;
, en cuyo casothis
seráundefined
Si se llama a una función con
new
lathis
que será un nuevo contexto, no hará referencia a lo globalthis
.Las funciones que crea se convierten en objetos de función. Obtienen automáticamente una
prototype
propiedad especial , que es algo a lo que puede asignar valores. Cuando crea una instancia al llamar a su funciónnew
, obtiene acceso a los valores que asignó a laprototype
propiedad. Accede a esos valores usandothis
.Por lo general, es un error asignar matrices u objetos en el
prototype
. Si desea que las instancias tengan sus propios arreglos, créelos en la función, no en el prototipo.Puede usar
this
cualquier función en un objeto para referirse a otras propiedades en ese objeto. Esto no es lo mismo que una instancia creada connew
.En un controlador de eventos DOM de HTML,
this
siempre es una referencia al elemento DOM al que se adjuntó el eventoA menos que
bind
el contextoDentro de los atributos HTML en los que puede poner JavaScript,
this
hay una referencia al elemento.Puedes usar
eval
para accederthis
.Puede usar
with
para agregarthis
al alcance actual para leer y escribir en valoresthis
sin hacer referenciathis
explícita.jQuery en muchos lugares se
this
referirá a un elemento DOM.fuente
Daniel, ¡una explicación asombrosa! Un par de palabras en esta y buena lista de
this
puntero de contexto de ejecución en caso de controladores de eventos.En dos palabras,
this
en JavaScript señala el objeto desde el cual (o desde cuyo contexto de ejecución) se ejecutó la función actual y siempre es de solo lectura, no se puede configurar de todos modos (tal intento terminará con 'Inválido a la izquierda lado en el mensaje de la tarea.Para los controladores de eventos: los controladores de eventos en línea, como
<element onclick="foo">
, anulan cualquier otro controlador conectado antes y antes, así que tenga cuidado y es mejor mantenerse alejado de la delegación de eventos en línea. Y gracias a Zara Alaverdyan que me inspiró a esta lista de ejemplos a través de un debate disidente :)el.onclick = foo; // in the foo - obj
el.onclick = function () {this.style.color = '#fff';} // obj
el.onclick = function() {doSomething();} // In the doSomething - Window
el.addEventListener('click',foo,false) // in the foo - obj
el.attachEvent('onclick, function () { // this }') // window, all the compliance to IE :)
<button onclick="this.style.color = '#fff';"> // obj
<button onclick="foo"> // In the foo - window, but you can <button onclick="foo(this)">
fuente
Hay mucha confusión sobre cómo se interpreta "esta" palabra clave en JavaScript. Esperemos que este artículo descanse de una vez por todas. Y mucho más. Por favor lea el artículo completo cuidadosamente. Tenga en cuenta que este artículo es largo.
Independientemente del contexto en el que se utiliza, "this" siempre hace referencia al "objeto actual" en Javascript. Sin embargo, cuál es el "objeto actual" difiere según el contexto . El contexto puede ser exactamente 1 de los 6 siguientes:
A continuación se describe cada uno de estos contextos uno por uno:
Contexto global (es decir, fuera de todas las funciones):
Fuera de todas las funciones (es decir, en contexto global), el "objeto actual" (y, por lo tanto, el valor de "esto" ) es siempre el objeto "ventana" para los navegadores.
Llamada directa interna "Función no vinculada" :
Dentro de una llamada directa de "Función no vinculada", el objeto que invocó la llamada de función se convierte en el "objeto actual" (y, por lo tanto, el valor de "esto" ). Si se llama a una función sin un objeto actual explícito , el objeto actual es el objeto "ventana" (para el modo no estricto) o indefinido (para el modo estricto). Cualquier función (o variable) definida en el Contexto global se convierte automáticamente en una propiedad del objeto "ventana". Por ejemplo, supongamos que la función se define en el Contexto global como
se convierte en propiedad del objeto de ventana, como si lo hubiera definido como
En "Modo no estricto", Llamar / Invocar esta función directamente a través de "UserDefinedFunction ()" automáticamente la llamará / invocará como "window.UserDefinedFunction ()" haciendo "window" como el "objeto actual" (y por lo tanto el valor de " esto " ) dentro de " UserDefinedFunction ". Invocar esta función en" Modo no estricto "dará como resultado lo siguiente
En "Modo estricto", Calling / invocación de la función directamente a través de "UserDefinedFunction ()" será "NO" llamar automáticamente / alegar ésta como "window.UserDefinedFunction ()" .Hence el "objeto actual" (y el valor de "este" ) dentro de "UserDefinedFunction" será indefinido . Invocar esta función en "Modo estricto" dará como resultado lo siguiente
Sin embargo, invocarlo explícitamente usando un objeto de ventana dará como resultado lo siguiente
Veamos otro ejemplo. Por favor mira el siguiente código
En el ejemplo anterior vemos que cuando se invocó "UserDefinedFunction" a través de o1 , "this" toma el valor de o1 y se muestra el valor de sus propiedades "a" y "b" . El valor de "c" y "d" se mostró como indefinido ya que o1 no define estas propiedades
De manera similar, cuando se invocó "UserDefinedFunction" a través de o2 , "this" toma el valor de o2 y se muestra el valor de sus propiedades "c" y "d" . El valor de "a" y "b" se muestran como indefinidos como lo hace o2 No define estas propiedades.
Llamada indirecta interior de "Función no vinculada" a través de functionName.call y functionName.apply :
Cuando se llama a una "Función no vinculada" a través de functionName.call o functionName.apply , el "objeto actual" (y, por lo tanto, el valor de "this" ) se establece en el valor del parámetro "this" (primer parámetro) pasado a la llamada / aplicar . El siguiente código demuestra lo mismo.
El código anterior muestra claramente que el valor "this" para cualquier "Función NO LIGADA" puede modificarse mediante call / apply . Además, si el parámetro "this" no se pasa explícitamente a call / apply , "objeto actual" (y, por lo tanto, el valor de "this") se establece en "window" en modo no estricto y "undefined" en modo estricto.
Llamada interna "Función vinculada " (es decir, una función que se ha vinculado al llamar a functionName.bind ):
Una función enlazada es una función cuyo "este" valor ha sido fijo. El siguiente código demostró cómo funciona "esto" en caso de función vinculada
Como se indica en el código anterior, "este" valor para cualquier "Función vinculada" NO PUEDE ser alterado a través de llamar / aplicar . Además, si el parámetro "this" no se pasa explícitamente a bind, "objeto actual" (y, por lo tanto, el valor de "this" ) se establece en "window" en modo No estricto y "undefined" en modo estricto. Una cosa más. La vinculación de una función ya vinculada no cambia el valor de "esto" . Permanece establecido como el valor establecido por la primera función de enlace.
Mientras que la creación de objetos a través de "nuevo" :
Dentro de una función constructora, el "objeto actual" (y, por lo tanto, el valor de "esto" ) hace referencia al objeto que se está creando actualmente a través de "nuevo", independientemente del estado de enlace de la función. Sin embargo, si el constructor es una función enlazada, se llamará con un conjunto predefinido de argumentos como el conjunto para la función enlazada.
Controlador interno de eventos DOM en línea :
Mire el siguiente fragmento de HTML
El "esto" en los ejemplos anteriores se refiere al elemento "botón" y al elemento "div" respectivamente.
En el primer ejemplo, el color de fuente del botón se establecerá en blanco cuando se haga clic en él.
En el segundo ejemplo, cuando se hace clic en el elemento "div" , llamará a la función OnDivClick con su segundo parámetro que hace referencia al elemento div en el que se hizo clic. Sin embargo, el valor de "esto" dentro de OnDivClick NO DEBE hacer referencia al elemento div en el que se hizo clic . Se establecerá como el "objeto de ventana" o "indefinido" en No estricto y modos Estricto respectivamente (si OnDivClick es una función independiente ) o se establecerá en un valor Límite predefinido (si OnDivClick es una función vinculada )
A continuación se resume todo el artículo.
En el contexto global "esto" siempre se refiere al objeto "ventana"
Cada vez que se invoca una función, se invoca en el contexto de un objeto ( "objeto actual" ). Si el objeto actual no se proporciona explícitamente, el objeto actual es el "objeto de ventana" en modo NO estricto y "indefinido" en modo estricto de forma predeterminada.
El valor de "esto" dentro de una función no vinculada es la referencia al objeto en el contexto del cual se invoca la función ( "objeto actual" )
El valor de "esto" dentro de una función no vinculada se puede anular mediante una llamada y aplicar métodos de la función.
El valor de "esto" se fija para una función enlazada y no se puede anular mediante una llamada y aplicar métodos de la función.
La función de enlace y ya enlazada no cambia el valor de "esto". Permanece establecido como el valor establecido por la primera función de enlace.
El valor de "esto" dentro de un constructor es el objeto que se está creando e inicializando
El valor de "this" dentro de un controlador de eventos DOM en línea es una referencia al elemento para el que se proporciona el controlador de eventos.
fuente
Probablemente el artículo más detallado y completo sobre
this
es el siguiente:Explicación suave de la palabra clave 'this' en JavaScript
La idea detrás
this
es comprender que los tipos de invocación de funciones tienen una importancia significativa en la configuración delthis
valor.Cuando tenga problemas para identificarse
this
, no se pregunte:pero no preguntarse:
Para una función de flecha (caso especial de transparencia de contexto) pregúntese:
Esta mentalidad es correcta cuando se trata
this
y le ahorrará dolor de cabeza.fuente
this
palabra clave?Esta es la mejor explicación que he visto: Comprenda JavaScripts esto con Clarity
Hay cuatro escenarios en los que esto puede ser confuso:
Da ejemplos de código, explicaciones y soluciones, lo que me pareció muy útil.
fuente
En términos seudoclásicos, la forma en que muchas conferencias enseñan la palabra clave 'this' es como un objeto instanciado por una clase o un constructor de objetos. Cada vez que se construye un nuevo objeto a partir de una clase, imagine que debajo del capó se crea y devuelve una instancia local de un objeto 'este'. Recuerdo que enseñó así:
fuente
this
es uno de los conceptos mal entendidos en JavaScript porque se comporta de manera poco diferente de un lugar a otro. Simplemente, sethis
refiere al "propietario" de la función que estamos ejecutando actualmente .this
ayuda a obtener el objeto actual (también conocido como contexto de ejecución) con el que trabajamos. Si comprende en qué objeto se ejecuta la función actual, puede comprender fácilmente quéthis
es la corrienteArriba creamos 3 variables con el mismo nombre 'val'. Uno en contexto global, uno dentro de obj y el otro dentro de innerMethod of obj. JavaScript resuelve los identificadores dentro de un contexto particular subiendo la cadena de alcance de local a global.
Pocos lugares donde
this
se puedan diferenciarLlamar a un método de un objeto
Cuando se ejecuta line1, JavaScript establece un contexto de ejecución (EC) para la llamada a la función, estableciendo
this
el objeto al que hace referencia lo que vino antes del último "." . así que en la última línea puedes entender quea()
se ejecutó en el contexto global que es elwindow
.Con constructor
this
puede usarse para referirse al objeto que se está creandoCuando
Person()
se ejecuta new, se crea un objeto completamente nuevo.Person
se llama ythis
se establece para hacer referencia a ese nuevo objeto.Llamada de función
Si omitimos la
new
palabra clave, sewhatIsThis
refiere al contexto más global que puede encontrar (window
)Con controladores de eventos.
Si el controlador de eventos está en línea, se
this
refiere al objeto globalAl agregar el controlador de eventos a través de JavaScript, se
this
refiere al elemento DOM que generó el evento..apply()
.call()
y.bind()
var that = this
significa en JavaScriptfuente
El valor de "esto" depende del "contexto" en el que se ejecuta la función. El contexto puede ser cualquier objeto o el objeto global, es decir, ventana.
Entonces, la semántica de "esto" es diferente de los lenguajes tradicionales de OOP. Y causa problemas: 1. cuando una función se pasa a otra variable (muy probablemente, una devolución de llamada); y 2. cuando se invoca un cierre desde un método miembro de una clase.
En ambos casos, esto se establece en ventana.
fuente
¿Con qué ayuda esto ? (La mayor confusión de 'esto' en javascript proviene del hecho de que generalmente no está vinculado a su objeto, sino al alcance de ejecución actual, que podría no ser exactamente cómo funciona, pero siempre me parece así) ver el artículo para una explicación completa)
fuente
Un poco de información sobre esta palabra clave
Registremos la
this
palabra clave en la consola en el ámbito global sin más código peroEn el cliente / navegador, la
this
palabra clave es un objeto global que eswindow
y
En Server / Node / Javascript runtime la
this
palabra clave también es un objeto global que esmodule.exports
Tenga en cuenta que
exports
es solo una referencia amodule.exports
fuente
este uso para Scope como este
El valor de txt1 y txt es el mismo en el ejemplo anterior $ (this) = $ ('# tbleName tbody tr') es Same
fuente
Tengo una opinión diferente sobre
this
de las otras respuestas que espero sean útiles.Una forma de ver JavaScript es ver que solo hay 1 forma de llamar a una función 1 . Está
Siempre se proporciona algún valor para
objectForThis
.Todo lo demás es azúcar sintáctica para
functionObject.call
Entonces, todo lo demás se puede describir por cómo se traduce
functionObject.call
.Si solo llama a una función, entonces
this
es el "objeto global" que en el navegador es la ventanaEn otras palabras,
fue traducido efectivamente a
Tenga en cuenta que si utiliza el modo estricto, entonces
this
seráundefined
lo que significa
En otras palabras,
fue traducido efectivamente a
En JavaScript hay operadores como
+
y-
y*
. También existe el operador de punto que es.
El
.
operador cuando se usa con una función a la derecha y un objeto a la izquierda significa efectivamente "pasar objeto comothis
a función".Ejemplo
En otras palabras se
bar.foo()
traduce enconst temp = bar.foo; temp.call(bar);
Tenga en cuenta que no importa cómo se creó la función (principalmente ...). Todo esto producirá los mismos resultados.
De nuevo, todos estos son solo azúcar sintáctica para
Otra arruga es la cadena prototipo. Cuando usa
a.b
JavaScript, primero busca en el objeto al que se hace referencia directamentea
para la propiedadb
. Sib
no se encuentra en el objeto, JavaScript buscará en el prototipo del objeto para encontrarlob
.Hay varias formas de definir el prototipo de un objeto, la más común en 2019 es la
class
palabra clave. A los efectos dethis
aunque no importa. Lo que importa es que, como se ve en el objetoa
de la propiedadb
si encuentra la propiedadb
en el objeto o en ella de cadena de prototipo sib
termina siendo una función a continuación, las mismas reglas que se aplican por encima. Lasb
referencias a funciones se llamarán utilizando elcall
método y pasandoa
llamarán como objectForThis como se muestra al principio de esta respuesta.Ahora. Imaginemos que hacemos una función que se establece explícitamente
this
antes de llamar a otra función y luego llamarla con el.
operador (punto)Siguiendo la traducción a usar
call
, seobj.bar()
convierteconst temp = obj.bar; temp.call(obj);
. Cuando ingresamos a labar
función que llamamos,foo
pero pasamos explícitamente en otro objeto por objectForThis, así que cuando llegamos a foothis
es ese objeto interno.Esto es lo que hacen ambas funciones
bind
y=>
efectivamente. Son más azúcar sintáctica. Construyen efectivamente una nueva función invisible exactamente como labar
anterior que se establece explícitamentethis
antes de llamar a cualquier función que se especifique. En el caso de bindthis
se establece a lo que sea que le pasebind
.Tenga en cuenta que si
functionObject.bind
no existiera podríamos hacer el nuestro asíy entonces podríamos llamarlo así
Funciones de flecha, el
=>
operador es azúcar sintáctico para enlacees lo mismo que
Al igual que
bind
, se crea una nueva función invisible que llama a la función dada con un valor enlazadoobjectForThis
pero a diferenciabind
del objeto a enlazar está implícito. Es lothis
que sea que sea cuando el=>
se usa operador.Entonces, al igual que las reglas anteriores
obj.foo()
se traduce en loconst temp = obj.foo; temp.call(obj);
que significa que el operador de flecha en el interiorfoo
se uniráobj
a una nueva función invisible y devolverá esa nueva función invisible que está asignadab
.b()
funcionará como siempre tieneb.call(window)
ob.call(undefined)
llama a la nueva función invisible quefoo
creó. Esa función invisible ignora lothis
pasado y pasaobj
como objectForThis` a la función de flecha.El código anterior se traduce en
1
apply
es otra función similar acall
Pero a partir de ES6 conceptualmente, incluso puede traducir eso en
fuente
this
Javascript Resumen :this
está determinado por cómo no se invoca la función, dónde se creó.this
está determinado por el Objeto que queda del punto. (window
en el espacio global)this
refiere al elemento DOM en el que se llamó el evento.new
palabra clave, el valor dethis
refiere al objeto recién creadothis
las funciones:call
,apply
,bind
Ejemplo:
Ejemplo de oyentes de eventos:
Constructor de ejemplo:
fuente
Para comprender "esto" correctamente, uno debe comprender el contexto, el alcance y la diferencia entre ellos.
Alcance : en javascript, el alcance está relacionado con la visibilidad de las variables, el alcance se logra mediante el uso de la función. (Lea más sobre el alcance)
Contexto : el contexto está relacionado con los objetos. Se refiere al objeto al que pertenece una función. Cuando utiliza la palabra clave "this" de JavaScript, se refiere al objeto al que pertenece la función. Por ejemplo, dentro de una función, cuando dice: "this.accoutNumber", se refiere a la propiedad "accoutNumber", que pertenece al objeto al que pertenece esa función.
Si el objeto "myObj" tiene un método llamado "getMyName", cuando la palabra clave JavaScript "this" se usa dentro de "getMyName", se refiere a "myObj". Si la función "getMyName" se ejecutó en el ámbito global, entonces "esto" se refiere al objeto de la ventana (excepto en modo estricto).
Ahora veamos un ejemplo:
El código de ejecución anterior en la salida del navegador:
De acuerdo con la salida que se encuentra dentro del contexto del objeto de la ventana, también es visible que el prototipo de la ventana se refiere al Objeto.
Ahora intentemos dentro de una función:
Salida:
El resultado es el mismo porque registramos 'esta' variable en el ámbito global y lo registramos en el ámbito funcional, no cambiamos el contexto. En ambos casos, el contexto era el mismo, relacionado con el objeto viuda .
Ahora creemos nuestro propio objeto. En javascript, puede crear un objeto de muchas maneras.
Salida:
Entonces, a partir del ejemplo anterior, encontramos que 'esta' palabra clave se refiere a un nuevo contexto que está relacionado con myObj, y myObject también tiene una cadena de prototipo para Object.
Vamos a lanzar otro ejemplo:
salida: tiene sentido ¿verdad? (leer comentarios)
Si tiene problemas para comprender el ejemplo anterior, intentemos con nuestra propia devolución de llamada;
salida:
Ahora, comprendamos Alcance, Self, IIFE y THIS cómo se comporta
La salida es bastante impresionante, ¿verdad?
fuente
Respuesta simple:
La palabra clave "this" siempre depende del contexto de invocación. Se mencionan a continuación.
LA FUNCIÓN SE LLAMA CON NUEVA PALABRA CLAVE
Si se llama a la función con la palabra clave NEW, THIS estará vinculada al objeto recién creado.
En lo anterior, esto estará vinculado al objeto 'myCar'
LA FUNCIÓN SE LLAMA EXPLÍCITAMENTE UTILIZANDO MÉTODOS DE LLAMADA Y APLICACIÓN.
En este caso, THIS estará vinculado al objeto que se pasa explícitamente a la función.
SI LA FUNCIÓN SE LLAMA AL OBJETO IMPLÍCITAMENTE, ESTARÁ LIGADO A ESE OBJETO
CUANDO LA FUNCIÓN SE LLAMA SIN NINGÚN CONTEXTO, ESTO ESTARÁ LIGADO AL OBJETO GLOBAL
EN MODO ESTRICTO ESTO NO SERÁ DEFINIDO
fuente