Me he dado cuenta de que no parece haber una explicación clara de qué es la thispalabra 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 thisfunciona y cuándo debe usarse?
javascript
this
Maxim Gershkovich
fuente
fuente

thispeter.michaux.ca/articles/javascript-widgets-without-thisthispalabra 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
thisy 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 (objen 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
thisArgque 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.prototypefunciones, 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.prototypefunciones, lo dadocallbackfnse llama en un contexto de ejecución donde ThisBinding se establecethisArgsi 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 referenciathisa funciones de biblioteca, debe consultar la documentación para ver las garantías sobre cuál es el valor dethiscuando 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
newoperador, 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 dethises 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
thisen la línea marcada? ¿Por qué?¿Cuál es el valor de
thisen la línea marcada cuandoobj.staticFunction()se ejecuta? ¿Por qué?¿Cuál es el valor de
thisen la línea marcada? ¿Por qué?¿Cuál es el valor de
thisen la línea marcada? ¿Por qué?¿Cuál es el valor de
thisen la línea marcada? ¿Por qué?fuente
setTimeoutejemplo tiene unathisdewindow(global).La
thispalabra clave se comporta de manera diferente en JavaScript en comparación con otros idiomas. En lenguajes orientados a objetos, lathispalabra clave se refiere a la instancia actual de la clase. En JavaScript, el valor dethisestá 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
thisen contexto global, está vinculado al objeto global (windowen el navegador)Cuando se usa
thisdentro de una función definida en el contexto global,thistodavía está vinculada al objeto global, ya que la función se convierte en un método de contexto global.Arriba
f1se hace un método de objeto global. Por lo tanto, también podemos llamarlo en elwindowobjeto de la siguiente manera:2. Cuando se usa dentro del método de objeto
Cuando utiliza una
thispalabra clave dentro de un método de objeto,thisestá 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
thisestá vinculado al padre inmediato.Incluso si agrega la función explícitamente al objeto como método, sigue las reglas anteriores, es decir,
thisapunta al objeto primario inmediato.3. Al invocar la función sin contexto
Cuando utiliza
thisuna función interna que se invoca sin ningún contexto (es decir, no en ningún objeto), está vinculada al objeto global (windowen 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.newoperador.A continuación probé todas las cosas que hicimos con Object y
thissuperiores, 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
newpalabra clave), elthiscuerpo 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,
thisdentro 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.thisque 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 estableceobj1como el valor dethisinsidefun()y llama a losfun()elementos que pasanargsArraycomo sus argumentos.fun.call(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Estableceobj1como el valor dethisinsidefun()y llama afun()pasararg1, arg2, arg3, ...como sus argumentos.fun.bind(obj1 [, arg1 [, arg2 [,arg3 [, ...]]]])- Devuelve la referencia a la funciónfunconthisdiversión interna vinculada aobj1y parámetrosfunvinculados a los parámetros especificadosarg1, arg2, arg3,....apply,callybinddebe haberse hecho evidente.applypermite especificar los argumentos para funcionar como un objeto tipo matriz, es decir, un objeto con unalengthpropiedad numérica y propiedades enteras no negativas correspondientes. Mientras quecallpermite especificar los argumentos de la función directamente. Ambosapplyecallinmediatamente invocan la función en el contexto especificado y con los argumentos especificados. Por otro lado,bindsimplemente devuelve la función vinculada althisvalor 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.
thiscontroladores de eventos internosthisfunción de manejo de eventos directamente dentro se refiere al elemento correspondiente. Dicha asignación directa de funciones se puede hacer utilizando eladdeventListenermétodo o mediante los métodos tradicionales de registro de eventos comoonclick.thisdirectamente dentro de la propiedad de evento (like<button onclick="...this..." >) del elemento, se refiere al elemento.thisindirecto 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.
thisen la función de flecha ES6En una función de flecha,
thisse 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
thisla llamada no establece el valor de . Como el código no está en modo estricto, el valor dethissiempre 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 alwindowobjeto, 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
thisInvocació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
thisse registraría comowindow. Esto se debe a quewindowes la variable global en el alcance de un navegador web.Si ejecuta este mismo código en un entorno como node.js,
thisse 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,thisya no se referiría a la variable global en ninguno de los entornos. Esto se hace para evitar confusiones en modo estricto.thisserí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
forEachyslice, ya debería saber que lathisvariable en ese caso se refiere a la funciónObjectsobre la que llamó a esa función (tenga en cuenta que en javascript, casi todo es anObject, incluidosArraysyFunctions). Tome el siguiente código por ejemplo.Si un
Objectcontiene una propiedad que contiene unFunction, la propiedad se llama un método. Este método, cuando se llama, siempre tendrá suthisvariable configurada con laObjectque 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
thisya no se conserva en la nueva variable. Por ejemplo:Considerando un escenario más comúnmente práctico:
La
newpalabra claveConsidere una función constructora en Javascript:
¿Como funciona esto? Bueno, veamos qué sucede cuando usamos la
newpalabra clave.newpalabra clave inmediatamente inicializaría unObjecttipoPerson.Objecttiene su constructor establecido enPerson. Además, tenga en cuenta que solotypeof awalvolveríaObject.Objectse le asignaría el prototipo dePerson.prototype. Esto significa que cualquier método o propiedad en elPersonprototipo estaría disponible para todas las instancias dePerson, inclusoawal.Personmisma ahora se invoca;thissiendo 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
constructorfunciones reales . Son funciones normales ynewse 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:
callyapplyEntonces sí, dado que los
functions 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 soncallyapply, y ambos pueden usarse para manipular el valor dethisen 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 establecethisla funciónfoocomo referenciathisArg. Todos los demás parámetros pasadoscallse pasan a la funciónfoocomo 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 dethisen cualquier función.applyes casi lo mismo quecallaceptar que solo toma dos parámetros:thisArgy una matriz que contiene los argumentos que se pasarán a la función. Entonces, lacallllamada anterior se puede traducir deapplyesta manera:Tenga en cuenta que
callyapplypuede anular el valor de lathisinvocación del método set by dot que discutimos en la segunda viñeta. Suficientemente simple :)Presentando ...
bind!bindes hermano decallyapply. También es un método heredado por todas las funciones delFunctionconstructor global en Javascript. La diferencia entrebindecall/applyes que tantocallyapplyen realidad se invoca la función.bind, por otro lado, devuelve una nueva función con elthisArgyargumentspreestablecido. Tomemos un ejemplo para comprender mejor esto:¿Ves la diferencia entre los tres? Es sutil, pero se usan de manera diferente. Me gusta
callyapply,bindtambién anulará el valor dethisestablecer por invocación de método de punto.También tenga en cuenta que ninguna de estas tres funciones cambia la función original.
callyapplydevolvería el valor de las funciones recién construidas, mientrasbindque devolverá la función recién construida, lista para ser llamada.Cosas extra, copia esto
A veces, no le gusta el hecho de que
thiscambie con el alcance, especialmente el alcance anidado. Eche un vistazo al siguiente ejemplo.En el código anterior, vemos que el valor de
thiscambió con el alcance anidado, pero queríamos el valor delthisalcance original. Así que 'copiado'thisathaty utilizamos la copia en lugar dethis. Inteligente, ¿eh?Índice:
thispor defecto?newpalabra clave?thisconcallyapply?bind.thispara 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:
(función (valor) { this.value = value; $ ('. algunos elementos'). each (function (elt) { elt.innerHTML = this.value; // ¡¡UH oh!! posiblemente indefinido }); }) (2);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:(función (valor) { var self = esto; // pequeño cambio self.value = value; $ ('. algunos elementos'). each (function (elt) { elt.innerHTML = self.value; // ¡uf! == 2 }); }) (2);Pruébalo; le comenzará a gustar este patrón de programación
fuente
thispalabra 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.thisNo 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), perothisestá 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
thistema.¿Cómo se
thisdetermina 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".
thisno 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 elwindowobjeto. Por lo tanto,thisen una función global se refiere (y tiene el valor de) elwindowobjeto global .Cuando
use strict,thisen funciones globales y anónimas que no están vinculadas a ningún objeto tiene un valor deundefined.La
thispalabra clave se malinterpreta más cuando: 1) tomamos prestado un método que usathis, 2) asignamos un método que usathisa una variable, 3) una función que usathisse pasa como una función de devolución de llamada y 4)thisse 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
thisenlace 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 elthismecanismo tradicional en favor de un alcance léxico más ampliamente entendido. (1)Referencias
fuente
thisen 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;thisse 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,
thisse referirá al objeto de la ventana.fuente
Cada contexto de ejecución de Javascript tiene un presente que tendrá el parámetro por:
evalPuede establecer el valor de esto usando
func.call,func.applyofunc.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
thisen 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.bindetc. - Sushilthisno no hacer referencia ámbito de una función.thishará 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.thisy 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),thisy el alcance se relacionan de una manera bastante mínima con las funciones de flecha wrt (la funciónthisen una flecha se hereda de su alcance adjunto), perothisnunca se refiere a un alcance.Aquí es una buena fuente de
thisenJavaScript.Aquí está el resumen:
global esto
En un navegador, en el ámbito global,
thises elwindowobjetoAl
nodeusar la respuesta,thises el espacio de nombres superior. Puedes referirte a él comoglobal.Al
nodeejecutar desde un script,thisen el ámbito global comienza como un objeto vacío. No es lo mismo queglobalfunciona esto
Excepto en el caso de los controladores de eventos DOM o cuando
thisArgse proporciona un (ver más abajo), tanto en el nodo como en un navegador utilizandothisuna función que no se llama connewreferencias al alcance global ...Si usa
use strict;, en cuyo casothisseráundefinedSi se llama a una función con
newlathisque 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
prototypepropiedad 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 laprototypepropiedad. 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
thiscualquier 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,
thissiempre es una referencia al elemento DOM al que se adjuntó el eventoA menos que
bindel contextoDentro de los atributos HTML en los que puede poner JavaScript,
thishay una referencia al elemento.Puedes usar
evalpara accederthis.Puede usar
withpara agregarthisal alcance actual para leer y escribir en valoresthissin hacer referenciathisexplícita.jQuery en muchos lugares se
thisreferirá a un elemento DOM.fuente
Daniel, ¡una explicación asombrosa! Un par de palabras en esta y buena lista de
thispuntero de contexto de ejecución en caso de controladores de eventos.En dos palabras,
thisen 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 - objel.onclick = function () {this.style.color = '#fff';} // objel.onclick = function() {doSomething();} // In the doSomething - Windowel.addEventListener('click',foo,false) // in the foo - objel.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
thises el siguiente:Explicación suave de la palabra clave 'this' en JavaScript
La idea detrás
thises comprender que los tipos de invocación de funciones tienen una importancia significativa en la configuración delthisvalor.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
thisy le ahorrará dolor de cabeza.fuente
thispalabra 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
thises uno de los conceptos mal entendidos en JavaScript porque se comporta de manera poco diferente de un lugar a otro. Simplemente, sethisrefiere al "propietario" de la función que estamos ejecutando actualmente .thisayuda 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éthises 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
thisse 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
thisel 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
thispuede usarse para referirse al objeto que se está creandoCuando
Person()se ejecuta new, se crea un objeto completamente nuevo.Personse llama ythisse establece para hacer referencia a ese nuevo objeto.Llamada de función
Si omitimos la
newpalabra clave, sewhatIsThisrefiere al contexto más global que puede encontrar (window)Con controladores de eventos.
Si el controlador de eventos está en línea, se
thisrefiere al objeto globalAl agregar el controlador de eventos a través de JavaScript, se
thisrefiere al elemento DOM que generó el evento..apply().call()y.bind()var that = thissignifica 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
thispalabra clave en la consola en el ámbito global sin más código peroEn el cliente / navegador, la
thispalabra clave es un objeto global que eswindowy
En Server / Node / Javascript runtime la
thispalabra clave también es un objeto global que esmodule.exportsTenga en cuenta que
exportses solo una referencia amodule.exportsfuente
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
thisde 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.callEntonces, todo lo demás se puede describir por cómo se traduce
functionObject.call.Si solo llama a una función, entonces
thises 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
thisseráundefinedlo 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 comothisa 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.bJavaScript, primero busca en el objeto al que se hace referencia directamenteapara la propiedadb. Sibno 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
classpalabra clave. A los efectos dethisaunque no importa. Lo que importa es que, como se ve en el objetoade la propiedadbsi encuentra la propiedadben el objeto o en ella de cadena de prototipo sibtermina siendo una función a continuación, las mismas reglas que se aplican por encima. Lasbreferencias a funciones se llamarán utilizando elcallmétodo y pasandoallamarán como objectForThis como se muestra al principio de esta respuesta.Ahora. Imaginemos que hacemos una función que se establece explícitamente
thisantes 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 labarfunción que llamamos,foopero pasamos explícitamente en otro objeto por objectForThis, así que cuando llegamos a foothises ese objeto interno.Esto es lo que hacen ambas funciones
bindy=>efectivamente. Son más azúcar sintáctica. Construyen efectivamente una nueva función invisible exactamente como labaranterior que se establece explícitamentethisantes de llamar a cualquier función que se especifique. En el caso de bindthisse establece a lo que sea que le pasebind.Tenga en cuenta que si
functionObject.bindno 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 enlazadoobjectForThispero a diferenciabinddel objeto a enlazar está implícito. Es lothisque 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 interiorfoose uniráobja 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 quefoocreó. Esa función invisible ignora lothispasado y pasaobjcomo objectForThis` a la función de flecha.El código anterior se traduce en
1
applyes otra función similar acallPero a partir de ES6 conceptualmente, incluso puede traducir eso en
fuente
thisJavascript Resumen :thisestá determinado por cómo no se invoca la función, dónde se creó.thisestá determinado por el Objeto que queda del punto. (windowen el espacio global)thisrefiere al elemento DOM en el que se llamó el evento.newpalabra clave, el valor dethisrefiere al objeto recién creadothislas funciones:call,apply,bindEjemplo:
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:
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