Acabo de encontrar una situación interesante en JavaScript. Tengo una clase con un método que define varios objetos usando notación literal de objeto. Dentro de esos objetos, thisse está utilizando el puntero. Por el comportamiento del programa, deduje que el thispuntero se refiere a la clase en la que se invocó el método, y no al objeto creado por el literal.
Esto parece arbitrario, aunque es la forma en que esperaría que funcione. ¿Es este comportamiento definido? ¿Es seguro para todos los navegadores? ¿Hay algún razonamiento subyacente por qué está más allá de lo que dice "la especificación lo dice" (por ejemplo, ¿es consecuencia de alguna decisión / filosofía de diseño más amplia)? Ejemplo de código reducido:
// inside class definition, itself an object literal, we have this function:
onRender: function() {
this.menuItems = this.menuItems.concat([
{
text: 'Group by Module',
rptletdiv: this
},
{
text: 'Group by Status',
rptletdiv: this
}]);
// etc
}

var signup = { onLoadHandler:function(){ console.log(this); return Type.createDelegate(this,this._onLoad); }, _onLoad: function (s, a) { console.log("this",this); }};Respuestas:
Canibalizado de otra publicación mía, aquí hay más de lo que siempre quisiste saber sobre esto .
Antes de comenzar, esto es lo más importante que debe tener en cuenta sobre Javascript, y repetirse a sí mismo cuando no tiene sentido. Javascript no tiene clases (ES6
classes azúcar sintáctico ). Si algo parece una clase, es un truco inteligente. Javascript tiene objetos y funciones . (eso no es 100% preciso, las funciones son solo objetos, pero a veces puede ser útil pensar en ellas como cosas separadas)La variable this está asociada a funciones. Cada vez que se invoca una función, esto se da un cierto valor, dependiendo de cómo se invoca la función. Esto a menudo se llama patrón de invocación.
Hay cuatro formas de invocar funciones en javascript. Puede invocar la función como método , como función , como constructor y con apply .
Como un método
Un método es una función adjunta a un objeto.
Cuando se invoca como un método, este se enlaza con el objeto de la función / método es una parte de. En este ejemplo, esto estará obligado a engañar.
Como una función
Si tiene una función independiente, esta variable estará vinculada al objeto "global", casi siempre el objeto de ventana en el contexto de un navegador.
Esto puede ser lo que te hace tropezar , pero no te sientas mal. Muchas personas consideran que esta es una mala decisión de diseño. Dado que una devolución de llamada se invoca como una función y no como un método, es por eso que está viendo lo que parece ser un comportamiento inconsistente.
Muchas personas solucionan el problema haciendo algo como, um, esto
Define una variable que apunta a esto . Cierre (un tema de todo es propio) mantiene que los rodea, por lo que si se llama a la barra como una devolución de llamada, todavía tiene una referencia.
NOTA: en
use strictmodo si se usa como función,thisno está vinculado a global. (Lo esundefined)Como constructor
También puede invocar una función como constructor. Según la convención de nomenclatura que está utilizando (TestObject), esto también puede ser lo que está haciendo y lo que lo está tropezando .
Invoca una función como Constructor con la nueva palabra clave.
Cuando se invoca como un constructor, se creará un nuevo objeto, y este estará obligado a ese objeto. Nuevamente, si tiene funciones internas y se usan como devoluciones de llamada, las invocará como funciones, y esto estará vinculado al objeto global. Usa esa var that = este truco / patrón.
Algunas personas piensan que el constructor / nueva palabra clave fue un hueso lanzado a los programadores tradicionales de Java / OOP como una forma de crear algo similar a las clases.
Con el método Apply
Finalmente, cada función tiene un método (sí, las funciones son objetos en Javascript) llamado "aplicar". Aplicar le permite determinar cuál será el valor de esto , y también le permite pasar una serie de argumentos. Aquí hay un ejemplo inútil.
fuente
thisseráundefinedpara invocaciones de funciones.thisno tiene nada que ver con el alcance. Te refieres al objeto global .this.confusing = 'hell yeah';lo mismo quevar confusing = 'hell yeah';? Entonces, ¿ambos permitiránmyObject.confusing? Sería bueno si no solo para que pueda usarthispara crear las propiedades y otras variables para el trabajo interno.function Foo(thought){ this.confusing = thought; }y luegovar myObject = new Foo("hell yeah");Llamadas a funciones
Las funciones son solo un tipo de objeto.
Todos los objetos de función tienen métodos de llamada y aplicación que ejecutan el objeto de función al que están llamados.
Cuando se llama, el primer argumento de estos métodos especifica el objeto al que hará referencia la
thispalabra clave durante la ejecución de la función, si se usanulloundefined, el objeto global,windowparathis.Por lo tanto, llamando a una función ...
... con paréntesis -
foo()- es equivalente afoo.call(undefined)ofoo.apply(undefined), que es efectivamente el mismo quefoo.call(window)ofoo.apply(window).Los argumentos adicionales a
callse pasan como argumentos a la llamada a la función, mientras que un único argumento adicional aapplypuede especificar los argumentos para la llamada a la función como un objeto tipo Array.Por lo tanto,
foo(1, 2, 3)es equivalente afoo.call(null, 1, 2, 3)ofoo.apply(null, [1, 2, 3]).Si una función es propiedad de un objeto ...
... acceder a una referencia a la Función a través del objeto y llamarla entre paréntesis -
obj.foo()- es equivalentefoo.call(obj)ofoo.apply(obj).Sin embargo, las funciones mantenidas como propiedades de los objetos no están "vinculadas" a esos objetos. Como puede ver en la definición de
objarriba, dado que las funciones son solo un tipo de objeto, se pueden hacer referencia a ellas (y, por lo tanto, se pueden pasar por referencia a una llamada de función o devolverse por referencia desde una llamada de función). Cuando se pasa una referencia a una Función, no se lleva información adicional sobre el lugar desde el que se pasó, por lo que sucede lo siguiente:La llamada a nuestra referencia de función,
bazno proporciona ningún contexto para la llamada, por lo que es efectivamente igual quebaz.call(undefined), por lo quethistermina haciendo referenciawindow. Si queremosbazsaber que perteneceobj, de alguna manera debemos proporcionar esa información cuandobazse llama, que es donde entra en juego el primer argumentocalloapplycierre.Cadenas de alcance
Cuando se ejecuta una función, crea un nuevo ámbito y tiene una referencia a cualquier ámbito de inclusión. Cuando se crea la función anónima en el ejemplo anterior, tiene una referencia al ámbito en el que se creó, que es
bindel ámbito. Esto se conoce como un "cierre".Cuando intente acceder a una variable, se recorre esta "cadena de alcance" para encontrar una variable con el nombre dado: si el alcance actual no contiene la variable, observe el siguiente alcance en la cadena, y así sucesivamente hasta llegar a El alcance global. Cuando se devuelve la función anónima y
bindtermina de ejecutarse, la función anónima aún tiene una referencia albindalcance de la aplicación, por lo quebindel alcance no "desaparece".Dado todo lo anterior, ahora debería poder comprender cómo funciona el alcance en el siguiente ejemplo, y por qué la técnica para pasar una función alrededor de "pre-enlazado" con un valor particular de la
thismisma tendrá lugar cuando se llama funciona:fuente
Si. Y si.
El significado de
thises bastante simple de deducir:thisse usa dentro de una función constructora, y la función se invocó con lanewpalabra clave, sethisrefiere al objeto que se creará.thisseguirá significando el objeto incluso en métodos públicos.thisse usa en cualquier otro lugar, incluidas las funciones protegidas anidadas , se refiere al alcance global (que en el caso del navegador es el objeto de ventana).El segundo caso es obviamente un defecto de diseño, pero es bastante fácil solucionarlo utilizando cierres.
fuente
En este caso, el interno
thisestá vinculado al objeto global en lugar de a lathisvariable de la función externa. Es la forma en que está diseñado el lenguaje.Consulte "JavaScript: las partes buenas" de Douglas Crockford para obtener una buena explicación.
fuente
Encontré un buen tutorial sobre el ECMAScript esto
Cualquier objeto puede usarse como este valor del contexto.
Esta característica es muy importante, porque a diferencia de las variables, este valor nunca participa en el proceso de resolución del identificador. Es decir, al acceder a esto en un código, su valor se toma directamente del contexto de ejecución y sin ninguna búsqueda de cadena de alcance. El valor de esto se determina solo una vez al ingresar al contexto.
En el contexto global, un valor de este es el objeto global en sí mismo (es decir, este valor aquí es igual a un objeto variable)
En el caso de un contexto de función, este valor en cada llamada de función puede ser diferente
Referencia Javascript-the-core y Capítulo-3-this
fuente