2012-06-25 21 views
16

In this commit hay un cambio no puedo explicarentendimiento palabra "this"

deferred.done.apply(deferred, arguments).fail.apply(deferred, arguments); 

convierte

deferred.done(arguments).fail(arguments); 

AFAIK, cuando se invoca una función como miembro de algún objeto como obj.func(), dentro de la función this está vinculado a obj, por lo que no tendría sentido invocar una función a través de apply() solo para enlazar this a obj. En cambio, de acuerdo con los comentarios, esto fue necesario debido a alguna implementación anterior de $.Callbacks.add.

Mi duda no se trata de jQuery, sino sobre el propio lenguaje Javascript: cuando se invoca una función como obj.func(), ¿cómo puede ser que en el interior func() la palabra clave thisno está obligado-obj?

+1

¿Cómo está relacionado el compromiso con su pregunta? '.apply' se usó para pasar' n' cantidad de argumentos a otra función, no para su contexto forzando habilidades. – Esailija

+0

@Esailija, ¡creo que entendiste! – Raffaele

+0

@Christoph Creo que entendió el punto. apply() no se usó para forzar el contexto, ya que * this * ya estaba * colocado correctamente * (y esto responde a mi pregunta) – Raffaele

Respuesta

5

Mi duda no se trata de jQuery, pero sobre el lenguaje Javascript sí: cuando se invoca una función como obj.func(), ¿cómo puede ser que dentro func() la palabra clave this no está obligado a obj?

Bueno, la única forma en que esto es posible si es obj.func referencia a una función bound, entonces no importa cómo se llame. En ese caso, no importa cómo se llama a la función, si lo hace obj.func(), func(), func.call({}), func.apply({}) no importa en absoluto. Sin embargo, no estoy seguro de cómo se relaciona el compromiso con esto.

Para aclarar, estoy respondiendo a la pregunta citada interpretado como:

dado una firma llamada como: obj.func(), ¿cómo es posible que this es noobj dentro de la función llamada para la llamada?

+0

Gran respuesta. Me pregunto si acabas de adivinar o si sabías que $ .Callbacks.add no puede manejar argumentos pasados ​​como una matriz como :) – Raffaele

+0

@Raffaele De hecho, tampoco. Es solo que '.aplicar (algo, argumentos)' es la única forma de pasar argumentos exactamente como se pasaron a la función de llamada. Bueno, supongo que podrías hacer algo con 'eval', pero eso no cuenta: D – Esailija

+0

Esto es aún mayor :) Así que la clave fue que reconociste la palabra clave ** arguments ** en el constructo * .apply (smth, arguments)) * e inmediatamente lo vinculó a llamadas encadenadas. A menudo, para resolver problemas difíciles, se necesita un profundo conocimiento del tema (experiencia) y * pensamiento lateral * :) – Raffaele

2

que sólo es posible por referencia a la función de otro objeto como tal

obj2.func = obj.func; 
obj2.func(); // 'this' now refers to obj2 

var func2 = obj.func; 
func2(); // 'this' now refers to the global window object 

o llamando .apply() o .call() para vincular this a cualquier objeto arbitrario.

+0

Esto es correcto, pero no responde mi pregunta :) Quería saber la diferencia, con respecto a ** este ** límite, entre * ab (args) * y * abapply (b, args) * Ver @ wnwall responder – Raffaele

+0

I * me * responder a su pregunta: "cuando se invoca una función como obj.func(), ¿cómo puede ser que en el interior func() la palabra clave this no está obligado a obj?" :-) Lo que afirmas como tu pregunta no está en la publicación principal: ¡quizás deberías actualizarlo! –

+0

Yo no lo creo: P De hecho, su ejemplo nunca llama * * func como miembro de obj * *: Le pasa a invocar el mismo objeto función, pero a medida que la propiedad de otro objeto (ya sea * obj2 * o * ventana*). Entonces, el valor de * this * es predecible y esperado. En su lugar, pregunté si cuando el motor ejecuta * a.b() * existe la posibilidad de que, dentro de * b() *, * this!= a *. – Raffaele

1

Siempre se llama a una función con un receptor, llamado this dentro de la función, que se proporciona al llamar.

Cuando se está escribiendo

obj.someFunc = function() {... 

usted no está diciendo que someFunc debe tener como obj receptor, que se limitan a decir que obj tiene una propiedad llamada someFunc cuyo valor es una función.

Si lo hace

var aFunc = obj.someFunc; 

gusta se hace en muchos lugares (haciendo referencia de devolución de llamada, por ejemplo) y después de eso

aFunc(); 

el receptor (this) es en este caso la ventana.

Esto se debe a que las funciones, en javascript, contrariamente a idiomas como java, son objetos de "primera clase", lo que significa que puede pasarlos como valores y no están vinculados a un único receptor preespecificado.

+0

Ver @Esailija y respuestas. Lo que dijiste es correcto, pero no aborda la cuestión, ya que vinculé explícitamente el código fuente y la función es realmente definida como obj.func() – Raffaele

+0

Gracias por tu comentario apuntando a la respuesta de Esailija. Tienes toda la razón. –

1

La versión abreviada que uso es this en JavaScript siempre se refiere al objeto del cual la función actualmente en ejecución es un método - excepto en el caso especial cuando el método es una devolución de llamada, cuando this se refiere al objeto al cual la devolución de llamada está vinculada (por ejemplo, un botón).

Editar: tenga en cuenta que una función global es como un método del objeto window.

This QuirksMode page me ayudó cuando estaba aprendiendo sobre ello.

5

Mientras que las otras respuestas tratan con su pregunta sobre la palabra clave this, no responden a su pregunta de por qué se está usando apply. Aquí está el truco: apply no se está utilizando para establecer la palabra clave this en ese ejemplo. En lugar de ello, está siendo utilizado para pasar arguments como los argumentos de los done y fail funciones.

Tome este ejemplo:

var x = { 
    a: function(a1, a2, a3) { 
     console.log(a1, a2, a3); 
    } 
} 

function callA() { 
    x.a.apply(x, arguments); 
    x.a(arguments); 
} 

callA('red', 'blue', 'green'); 

Si se ejecuta este código debería ver la diferencia entre x.a.apply(x, arguments); y x.a(arguments);. En la primera, a1, a2 y a3 son los respectivos colores "rojo", "azul" y "verde". En la segunda, a1 es un objeto de matriz-como [ "red", "blue", "green" ] y a2 y a3 son undefined.

Del mismo modo, en su ejemplo publicado, apply se está utilizando para pasar el objeto arguments correctamente, no para establecer la palabra clave this.

+0

+1, lo siento, este no puede ser el aceptado, pero Esailija es el primero (además de que mencionó objetos atados). Sin embargo, realmente aprecio la claridad y espero que la muestra de tu código pueda ayudar a otros a entender la verdadera pregunta como lo hiciste :) – Raffaele