2012-04-12 12 views
7

Estos están tomados de los tutoriales de Jquery vid de tuts-premium.
http://tutsplus.com/lesson/the-this-keyword/ Jeff explica a qué se refiere "esto" cada vez, pero no estoy seguro de haber captado el razonamiento detrás de todos.4 escenarios diferentes de 'esto'. ¿Cuál es la interpretación correcta?

E.g. 1

function doSomething(e) { 
e.preventDefault(); 
console.log(this); 
} 

$('a').on('click', doSomething); 

En este caso, "esto se refiere al elemento 'a'" (siendo en este caso el objeto padre)

supongo que es porque aquí la declaración equivale a:

$('a').on('click', function (e) { 
    e.preventDefault(); 
    console.log(this); 
    } 

Así que 'a' es el objeto principal

Por ej. 2

var obj = { 
    doIt: function(e){ 
    e.preventDefault(); 
    console.log(this); 
    } 
} 

$('a').on('click', obj.doIt); 

En este caso, "esto todavía se refiere al elemento 'a'" (* pero parece ser que no es el objeto padre?)

Parece que esta vez estamos llamando a un método, pero el declaración todavía equivale a lo mismo que Eg 1

* Una cosa en el tutorial me tiene un poco confundido. Pensé que 'esto' siempre se refiere al objeto principal, por lo que en este caso 'a' sigue siendo el objeto principal. Pero (a las 05.23 en el tutorial) infiere que no es el caso, indicando que "puede haber ocasiones en las que desee que 'esto' se refiera a su objeto principal que sería 'obj'", en cuyo caso crea e.g.3.

E.g. 3

var obj = { 
    doIt: function(){ 
    console.log(this); 
    } 
} 

$('a').on('click', function(e){  
obj.doIt(); 
     }; 
e.preventDefault(); 

En este caso "Esto se refiere al objeto obj"

supongo que esto con el hecho de que 'esto' está en una función anidada como esta declaración equivale a:

$('a').on('click', function(){  
function(){ console.log(this);} 
}; 
e.preventDefault(); 

Realmente no entiendo por qué, particularmente cuando leo en un artículo que en funciones anidadas 'this' "pierde su camino y se refiere al objeto principal (objeto ventana)".

EG4

var obj = { 
    doIt: function(){ 
    console.log(this);  
    } 
} 

$('a').on('click', function(e){  
     obj.doIt.call(this);    
     e.preventDefault(); 
}); 

En este caso "Esto se refiere a la 'a'"

Según guía definitiva Javascript "El primer argumento de ambos llamada() es el objeto sobre el cual la función debe invocarse " Aquí" este "es el usado como primer argumento. Pero "este" no es el objeto sobre el que se invocará la función?
Creo que entiendo que la función de llamada está ahí para invocar la función y usar su primer parámetro como un puntero a un objeto diferente, pero no entiendo por qué usar 'esto' significa que la función es invocada por 'a'. Tampoco es algo que haya visto en otros ejemplos de call().

Lo siento por una publicación tan mamut.Esperemos que alguien siga leyendo en esta etapa ...

+0

+1 porque es demasiado tarde aquí para que empiece a responder a esta excelente pregunta. Sin duda, alguien más lo hará pronto: es un punto vital y generalmente está mal cubierto en los tutoriales de JS. – jimw

+3

* "Pensé que 'esto' siempre se refiere al objeto principal ..." * No, no pienses en 'esto' como el objeto principal. Piénselo como un * contexto de llamada * cuyo valor se puede establecer de varias maneras diferentes, una de las cuales es llamar a un método desde un objeto. –

Respuesta

4

Espero que esto ayude a aclarar el problema, de hecho puede ser confuso.

  • Cuando this es floja en su código, se referirá al objeto global (en los navegadores web, es decir window).

    console.log(this); // window 
    
  • Cuando this está dentro de un método de objeto (como en su ejemplo, 3), se referirá al objeto. Esto se aplica a los objetos instanciados con new, o como literales de objeto (como en su ejemplo).

    var obj = { 
        doIt: function(e){ 
         console.log(this); 
        } 
    } 
    obj.doIt(); // obj 
    
  • Dentro de un controlador de eventos, this se referirá al objeto el evento está obligado a.

    // This is the plain js equivalent of your jQuery example 
    document.getElementsByTagName['a'][0].addEventListener('click', function(e){ 
        console.log(this); // the first anchor on the document 
    }); 
    
    // This is exactly the same: 
    var clickHandler = function(e){ 
        console.log(this); // the first anchor on the document 
    }; 
    document.getElementsByTagName['a'][0].addEventListener('click', clickHandler); 
    
    // Even if the handler is defined inside of another object, this will be 
    // the obj the event is bound to. It's the case of your E.g. 2 
    var obj = { 
        doIt: function(e){ 
         console.log(this); // the first anchor on the document 
        } 
    } 
    document.getElementsByTagName['a'][0].addEventListener('click', obj.doIt); 
    // When you pass obj.doIt to addEventListener above, you are passing a reference 
    // to that function. It's like "stealing" the function from the object 
    
  • Cuando un objeto se pasa como primer parámetro a Function.call o Function.apply, si this aparece dentro de la función que se referirá al objeto que ha pasado. Es una forma de forzar a lo que apunta this.

    var obj = { 
        doIt: function(){ 
         console.log(this); // window 
        } 
    } 
    obj.doIt.call(window); 
    
+0

Sin embargo, dado 'obj' con una función' doIt', si hacemos 'var fn = obj.doIt; fn() ',' this' se referirá a 'window' dentro de' fn'. –

+0

Sí, al igual que en mi ejemplo con 'addEventListener' (excepto que en ese caso señalará un nodo DOM, no' ventana'). Pero la lógica es la misma. – bfavaretto

0

La forma en que this se comporta en JavaScript es un poco confuso al principio. Básicamente, a diferencia de las variables (que tienen un alcance estático), this es dinámicamente con ámbito. Es decir, el valor de this se determina según donde llame al la función en lugar de donde la escribió.

Cuando pase su función a on, luego se llama desde un contexto donde this es el elemento en cuestión. Esto sucede sin importar de cómo obtuviste esa función. Es decir, a una función no le importa si accede usando sintaxis como obj.fn o simplemente su nombre fn --el valor de la expresión es el mismo en ambos casos.

Con otras cosas que no sean funciones, esto tiene sentido. Teniendo en cuenta:

var a = 10, 
    obj = { a : 10 }; 

que estará de acuerdo en que las expresiones a y obj.a tienen el mismo valor. Esto también es cierto para las funciones.

En resumen: el valor de this depende de dónde y cómo llame a la función en lugar de cómo y dónde la declaró o cómo se refirió a ella antes de llamarla.

+3

No deberíamos confundir 'this' con" scope ". Están completamente separados. Y 'this' no está determinado por * donde *, sino por * cómo * se llama a la función. –

+0

Mirando más de cerca, hay varias cosas mal. Me gusta ... * "... luego se llama desde un contexto donde este es el elemento en cuestión" *. Esto no hace diferencia. No hay transferencia del contexto adjunto al invocado a menos que lo transfiera manualmente usando '.call()' o '.apply()'. Y esto ... * "... a una función no le importa si accede usando sintaxis como' obj.fn' o simplemente su nombre 'fn'" * ... tampoco está bien. Hace una gran diferencia. –

+0

Mi punto era que la expresión 'f' y' obj.f' tienen el mismo valor (siempre que 'f' y' obj.f' apuntan a la misma función). Tal vez no fui lo suficientemente claro en eso. En cuanto al otro punto, puede cambiar el valor de 'this' sin' call' o 'apply' poniendo la función en el objeto. Por lo tanto, si * lo llama * desde un objeto o por sí mismo importa, pero solo por acceder a él (obteniendo la función como un valor) no importa. –

0

apreciar realmente estas respuestas chicos. He publicado en las primeras horas y he intentado (& necesario) para tomar un poco de tiempo para digerir sus comentarios.

https://developer.mozilla.org/en/JavaScript/Reference/Operators/this fue un gran grito. He leído bastantes artículos/tuts y este parece uno de los mejores.

Creo que la aclaración principal ha sido que el objeto vinculado a 'esto' está determinado por cómo/dónde se llamó a la función (contexto de llamada) en lugar de cómo o dónde se definió la función.

lo tanto, sólo para volver las cosas a la Q & Un alcance y tratar de responder a mi propia Q a la luz de lo que ustedes han respondido ...

P. ej 1 aquí: la función 'doSomething' fue llamado en el contexto del controlador de clic por lo que el objeto unido a 'esto' es "a"

P. ej 2 De nuevo el controlador de clic todavía está desencadenando la función por lo que el objeto unido a 'esto' es "a"

P. ej 3 En la función anidada, el contexto de llamada es obj.doIt(). Entonces, como dice en el tutorial, el objeto vinculado a 'esto' es "obj".

Aunque, basado en la lógica similar de developer.mozilla.org siguiente ejemplo, no es el objeto realmente unido a "obj.doIt":

o.b = {g: independent, prop: 42};   
console.log(o.b.g()); // logs 42   

"la esta unión sólo se ve afectado por la mayoría referencia de miembro inmediata .... esto dentro de la función se referirá a ob El hecho de que el objeto sea en sí mismo un miembro de o no tiene ninguna consecuencia, la referencia más inmediata es todo lo que importa ".

E.g. 4

Aquí - el trabajo de 'call' es invocar indirectamente la función como si fuera un método de un objeto nuevo, en este caso uno que hemos definido como 'this'. Aquí 'esto' se refiere a "a 'ya que es parte de la función activada por el manejador de clics.

Espero que esto esté un poco más cerca. Me siento como un tonto en esto (juego de palabras) porque las respuestas están siendo respondidas presentado a mí todavía no estoy del todo seguro de que estoy clavando el concepto.

Si tengo que arrastrarme de regreso a mi agujero por un tiempo para digerir suplico nuevo estado, accidente cursing Javascript & JQuery por solo un unas semanas.

Gracias de nuevo por todo el mundo la retroalimentación.

Cuestiones relacionadas