2008-12-16 32 views
85

Duplicar posible:
How can I pre-set arguments in JavaScript function call? (Partial Function Application)¿Cómo puedo pasar una referencia a una función, con parámetros?

necesito poder pasar una referencia a una función con un conjunto dado de parámetros.

Aquí es un ejemplo de que pasa una referencia sin parámetros:

var f = function() { 
    //Some logic here... 
}; 

var fr = f; //Here I am passing a reference to function 'f', without parameters 
fr(); //the 'f' function is invoked, without parameters 

Ahora lo que tengo que hacer es pasar la misma función f, pero esta vez tendría que pasar parámetros al referencia. Ahora, puedo hacerlo con una función anónima e invoco la función f con los parámetros dentro de la función de nueva creación, como por ejemplo:

var f = function() { 
     //Some logic here... 
    }; 

var fr = function (pars) { 
    f(pars); 
}; //Here I am creating an anonymous function, and invoking f inside it 

fr({p : 'a parameter'}); //Invoking the fr function, that will later invoke the f function with parameters 

Pero mi pregunta es, ¿Hay una manera de pasar una referencia directa a la f función Con los parámetros a fr, pero sin encerrarlo en una función anónima?

¿Qué necesito para asignar a fr para que sea invocable sin parámetros (fr()), por lo que se ejecuta f (1,2,3) cuando se invoca fr?

[ACTUALIZACIÓN] que siguieron Jason Bunting 's respuesta a here acerca de la función parcial y la función de JavaScript que los mensajes no es exactamente lo que estaba buscando. Aquí está la solución:

function partial(func /*, 0..n args */) { 
    var args = Array.prototype.slice.call(arguments).splice(1); 
    return function() { 
    var allArguments = args.concat(Array.prototype.slice.call(arguments)); 
    return func.apply(this, allArguments); 
    }; 
} 
+0

Por alguna razón, tuve problemas con la primera declaración (args var = Array.prototype.slice.call (argumentos) .splice (1);) y tuvo que usar esto en su lugar: var args = new Array(); para (var i = 1; i

+0

por si alguien necesita esto: 'Function.prototype.pass = function() { var args = arguments, func = this; return function() {func.apply (this, args);} }; ' –

Respuesta

77

lo que está después se llama aplicación función parcial.

No se deje engañar por aquellos que no entienden la sutil diferencia entre eso y currying, ellos son diferentes.

La aplicación de función parcial se puede utilizar para implementar, pero no es currying. Aquí es una cita de a blog post on the difference:

Cuando la aplicación parcial toma una función y de ella construye una función que toma menos argumentos, currificación construye funciones que tienen múltiples argumentos por la composición de funciones que cada uno tome un solo argumento.

Esto ya ha sido respondida, consulte esta pregunta para su respuesta: How can I pre-set arguments in JavaScript function call?

Ejemplo:

var fr = partial(f, 1, 2, 3); 

// now, when you invoke fr() it will invoke f(1,2,3) 
fr(); 

Una vez más, ver a esa pregunta para los detalles.

+0

¿Qué necesito asignar a' fr' para que sea invokable sin parámetros ('fr()'), por lo que f (1 , 2,3) se ejecuta cuando se invoca 'fr' –

+4

Nota para futuros lectores, asegúrese de incluir la función' parcial' proporcionada por Jason en [su otra respuesta] (http://stackoverflow.com/a/321527/ 1366033) – KyleMit

+2

Como alternativa a la función 'partial' de Jason, la biblioteca [UnderscoreJS] (http://underscorejs.org) también ofrece una función' _.partial'. – sfletche

-4

El siguiente es equivalente a su segundo bloque de código:

var f = function() { 
     //Some logic here... 
    }; 

var fr = f; 

fr(pars); 

Si desea pasar en realidad una referencia a una función a otra función, puede hacer algo como esto:

function fiz(x, y, z) { 
    return x + y + z; 
} 

// elsewhere... 

function foo(fn, p, q, r) { 
    return function() { 
     return fn(p, q, r); 
    } 
} 

// finally... 

f = foo(fiz, 1, 2, 3); 
f(); // returns 6 

Sin embargo, es casi seguro que es mejor utilizar un marco para este tipo de cosas.

2

También puede sobrecargar el prototipo de función:

// partially applies the specified arguments to a function, returning a new function 
Function.prototype.curry = function() { 
    var func = this; 
    var slice = Array.prototype.slice; 
    var appliedArgs = slice.call(arguments, 0); 

    return function() { 
     var leftoverArgs = slice.call(arguments, 0); 
     return func.apply(this, appliedArgs.concat(leftoverArgs)); 
    }; 
}; 

// can do other fancy things: 

// flips the first two arguments of a function 
Function.prototype.flip = function() { 
    var func = this; 
    return function() { 
     var first = arguments[0]; 
     var second = arguments[1]; 
     var rest = Array.prototype.slice.call(arguments, 2); 
     var newArgs = [second, first].concat(rest); 

     return func.apply(this, newArgs); 
    }; 
}; 

/* 
e.g. 

var foo = function(a, b, c, d) { console.log(a, b, c, d); } 
var iAmA = foo.curry("I", "am", "a"); 
iAmA("Donkey"); 
-> I am a Donkey 

var bah = foo.flip(); 
bah(1, 2, 3, 4); 
-> 2 1 3 4 
*/ 
Cuestiones relacionadas