2012-03-10 12 views
65

Tengo una pregunta sobre cómo se trata el puntero "this" en un escenario de función anidada.Javascript "este" puntero dentro de la función anidada

Digamos que inserto el siguiente código de muestra en una página web. Aparece un error cuando llamo a la función anidada "doSomeEffects()". Revisé Firebug e indica que cuando estoy en esa función anidada, el puntero "this" apunta en realidad al objeto "ventana" global, lo que no esperaba. No debo entender algo correctamente porque pensé que como declaraba la función anidada dentro de una función del objeto, debería tener un alcance "local" en relación con la función (es decir, el puntero "este" se referiría al objeto mismo como cómo está en mi primera declaración "si").

Cualquier puntero (sin juego de palabras) sería apreciado.

var std_obj = { 
    options : { rows: 0, cols: 0 }, 
    activeEffect : "none", 
    displayMe : function() { 

    // the 'this' pointer is referring to the std_obj 
    if (this.activeEffect=="fade") { } 

    var doSomeEffects = function() { 

     // the 'this' pointer is referring to the window obj, why? 
     if (this.activeEffect=="fade") { } 

    } 

    doSomeEffects(); 
    } 
}; 

std_obj.displayMe(); 
+0

¿Cuál es exactamente su pregunta? – Sarfraz

+2

Cuando se usa dentro de una función, 'this' se refiere al objeto sobre el cual se invoca la función. – approxiblue

+6

Lo que podría hacer en el ámbito externo es algo como 'var self = this;' y luego referirse a 'self' en la función interna a través del cierre. – Kai

Respuesta

96

En JavaScript del objeto this se basa realmente en la forma de hacer sus llamadas a funciones.

En general, existen tres formas de configurar el objeto this:

  1. someThing.someFunction(arg1, arg2, argN)
  2. someFunction.call(someThing, arg1, arg2, argN)
  3. someFunction.apply(someThing, [arg1, arg2, argN])

En todos los ejemplos anteriores el objeto this será someThing. Llamar a una función sin un objeto primario principal generalmente le proporcionará el objeto global que en la mayoría de los buscadores significa el objeto window.

8

Hay una diferencia entre las variables del gabinete y "esto". "esto" en realidad está definido por el invocador de la función, mientras que las variables explícitas permanecen intactas dentro del bloque de declaración de función conocido como el gabinete. Véase el siguiente ejemplo:

function myFirstObject(){ 
    var _this = this; 
    this.name = "myFirstObject"; 
    this.getName = function(){ 
     console.log("_this.name = " + _this.name + " this.name = " + this.name); 
    } 
} 

function mySecondObject(){ 
    var _this = this; 
    this.name = "mySecondObject"; 
    var firstObject = new myFirstObject(); 
    this.getName = firstObject.getName 
} 

var secondObject = new mySecondObject(); 
secondObject.getName(); 

se puede probar aquí: http://jsfiddle.net/kSTBy/

lo que está sucediendo en su función es "doSomeEffects()", que se está llamando explícitamente, esto significa contexto o el "presente" de la función es la ventana. si "doSomeEffects" fue un método prototipo, p. this.doSomeEffects en decir "myObject", entonces myObject.doSomeEffects() haría que "this" sea "myObject".

+4

para los perezosos e impacientes, este demo registra: '_this.name = myFirstObject this.name = mySecondObject' – ptim

23

this no es parte del ámbito de cierre, se puede considerar como un parámetro adicional a la función que está vinculada en el sitio de la llamada. Si el método no se llama como método, el objeto global se pasa como this. En el navegador, el objeto global es idéntico al window.Por ejemplo, considere la siguiente Funciton,

function someFunction() { 
} 

y el siguiente objeto,

var obj = { someFunction: someFunction }; 

Si se llama a la función utilizando la sintaxis de método como,

obj.someFunciton(); 

continuación this está obligado a obj.

Si llama algunaFuncion() directamente, como por ejemplo,

someFunction(); 

continuación this está ligado al objeto global, es decir window.

El trabajo más común en todo es capturar esto en el cierre, tales como,

displayMe : function() {  

    // the 'this' pointer is referring to the std_obj  
    if (this.activeEffect=="fade") { }  
    var that = this; 
    var doSomeEffects = function() {  

     // the 'this' pointer is referring to global 
     // that, however, refers to the outscope this 
     if (that.activeEffect=="fade") { }  
    }  

    doSomeEffects();   
}  
3

Como se explica por Kyle, podría utilizar call o apply para especificar this dentro de la función:

Aquí está ese concepto se aplica a su código:

var std_obj = { 
    options: { 
     rows: 0, 
     cols: 0 
    }, 
    activeEffect: "none", 
    displayMe: function() { 

     // the 'this' pointer is referring to the std_obj 
     if (this.activeEffect == "fade") {} 

     var doSomeEffects = function() { 
      // the 'this' pointer is referring to the window obj, why? 
      if (this.activeEffect == "fade") {} 
     } 

     doSomeEffects.apply(this,[]); 
    } 
}; 

std_obj.displayMe(); 

JsFiddle

4

Para comprender esta cuestión, trate de obtener la salida para el siguiente fragmento de

var myObject = { 
    foo: "bar", 
    func: function() { 
     var self = this; 
     console.log("outer func: this.foo = " + this.foo); 
     console.log("outer func: self.foo = " + self.foo); 
     (function() { 
      console.log("inner func: this.foo = " + this.foo); 
      console.log("inner func: self.foo = " + self.foo); 
     }()); 
    } 
}; 
myObject.func(); 

El código anterior de salida de la siguiente en la consola:

outer func: this.foo = bar 
outer func: self.foo = bar 
inner func: this.foo = undefined 
inner func: self.foo = bar 

En la función externa, tanto en el presente y auto referirse a myObject y por lo tanto ambos pueden referenciar y acceder a foo adecuadamente.

En la función interna, sin embargo, esto ya no hace referencia a myObject. Como resultado, este .foo no está definido en la función interna, mientras que la referencia a la variable local self permanece en el alcance y es accesible allí. (Antes de ECMA 5, esto en la función interna se referiría al objeto ventana global, mientras que, a partir de ECMA 5, esto en la función interna sería indefinido)

+1

En la función interna,' this' se refiere al objeto window (en un entorno de navegador) o al objeto GLOBAL (en un nodo entorno .js) – raneshu

+0

¿Por qué sucede eso? – setu

+0

@raneshu "use strict" y "this" ya no se refiere a la ventana – rofrol

15

Dado que esta parece ser una de las preguntas más votadas de este tipo, permítanme agregar, después de todos estos años, la solución ES6 que utiliza funciones de flecha:

var std_obj = { 
    ... 
    displayMe() { 
    ... 
    var doSomeEffects =() => { 
         ^^^^^^^ ARROW FUNCTION  
     // In an arrow function, the 'this' pointer is interpreted lexically, 
     // so it will refer to the object as desired. 
     if (this.activeEffect=="fade") { } 
    }; 
    ...  
    } 
}; 
+1

Ahora * ¡eso es * progreso! –

Cuestiones relacionadas