2011-09-18 15 views
15

Estaba navegando a través del JavaScript Garden cuando tropecé con el hack Function.call.apply que se utiliza para crear "envoltorios rápidos, sin encuadernar". Dice:¿Cuál es el propósito de usar Function.call.apply en JavaScript?

Otro truco es usar tanto la llamada como la aplicación juntas para crear envoltorios rápidos y sin unir.

function Foo() {} 

Foo.prototype.method = function(a, b, c) { 
    console.log(this, a, b, c); 
}; 

// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN 
Foo.method = function() { 

    // Result: Foo.prototype.method.call(this, arg1, arg2... argN) 
    Function.call.apply(Foo.prototype.method, arguments); 
}; 

Lo que no entiendo es por qué molestarse usando Function.call.apply cuando bastaría Function.apply. Después de todo, ambos son semánticamente equivalentes.

+0

Sí publiqué un enlace al [JavaScript Garden] (http://javascriptgarden.info/). Si desea ir directamente a la sección que contiene la publicación, haga clic en [aquí] (http://javascriptgarden.info/#function.arguments). –

+0

tnx, - parece que implican que este truco le da cierta velocidad ... pero, realmente, solo ** no lo use **. – c69

+2

@Aadit 'Function.call.apply' y' Function.apply' no puede ser el mismo aquí porque el primero aplica 'Function.call' mientras que el segundo trata de aplicar el constructor' Function'. Detalles en mi respuesta, pero apuesto a que si Ivo Wetzel viniera a responder esto, sería mucho más elocuente y comprensible. Esto es algo bastante profundo. Estoy de acuerdo en que probablemente no es algo que debas usar a menos que quieras que tus colegas gasten, oh no sé, una "media hora" tratando de entenderlo. :) –

Respuesta

13

No, Function.call.apply y Function.apply no son los mismos en este caso.

Digamos que la llamada original invoca

Foo.method(t, x, y, z) 

Con la llamada y se aplican juntos, como en el código JavaScript del jardín. Esto ejecuta

Function.call.apply(Foo.prototype.method, arguments); 

que es (sin apretar, escribiendo arguments en matriz de notación):

Function.call.apply(Foo.prototype.method, [t, x, y, z]); 

que invoca Function.call con this==Foo.prototype.method:

Foo.prototype.method.call(t, x, y, z) 

que llama Foo.prototype.method con this conjunto a t y argumentos x, y y z. Dulce. Al igual que en los comentarios. Hemos hecho con éxito una envoltura.

Supongamos que usted acaba de decir Function.apply en vez de Function.call.apply, que usted dice que es semánticamente equivalente. Usted tendría

Function.apply(Foo.prototype.method, arguments); 

que es (sin apretar)

Function.apply(Foo.prototype.method, [t, x, y, z]); 

el que llama a la función Function (uf!) Con this conjunto de Foo.prototype.method y argumentos t, x, y y z.

No es lo mismo en absoluto.

+0

Pero, ¿cuál es el propósito de tal envoltura? – c69

+3

El propósito es llamar a 'Foo.prototype.method' sin que esté vinculado a una instancia de' Foo'. En su lugar, debe ingresar _your own_ value para usarlo como el valor de 'this' dentro de' Foo.prototype.method'. ¿Por qué harías esto? Tal vez quiera hacer alguna programación funcional y la función que desea asignar o reducir o filtrar pasa a ser un método vinculado. Si no quiere que se vincule a un objeto, llama a un "envoltorio independiente". Sin embargo, esta es una terminología extraña, porque en última instancia está vinculando este método a su propio objeto (pero puede ignorarlo ...) –

+0

Ok, por lo que entendí, las siguientes afirmaciones son equivalentes: Function.call.apply (Foo.prototype.method, arguments); Foo.prototype.method.apply (argumentos [0], Array.prototype.slice.call (arguments, 1)); Ambos pueden sustituirse para crear envoltorios independientes. Sin embargo, el primer método es más corto, más rápido y más intuitivo. ¡Increíble! –

4

Significa que puede usar los métodos de un objeto en otro.

Un buen ejemplo son los argumentos variable de todas las funciones tienen, es como una matriz, pero no una matriz para que pueda llamar métodos de matriz de este modo:

Array.prototype.join.call(arguments, ","); 
+1

Pero, ¿qué hace el bit 'apply' en la pregunta original? –

+1

@CameronSkinner: el método 'apply' de un objeto de función ejecuta esa función, tratando el primer argumento como' this' en esa ejecución y el segundo argumento como 'arguments'. 'fn.apply (a, [b, c])' es equivalente a 'fn.call (a, b, c)'. – eyelidlessness

Cuestiones relacionadas