2008-12-16 7 views
85

Mögliche Duplizieren:
How can I pre-set arguments in JavaScript function call? (Partial Function Application)Wie kann ich einen Verweis auf eine Funktion mit Parametern übergeben?

Ich muss in der Lage einen Verweis auf eine Funktion mit einem bestimmten Satz von Parametern übergeben. Hier

ist ein Beispiel für Sie als Referenz ohne Parameter:

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 

Nun, was ich tun müssen, ist die gleiche f Funktion übergeben, aber dieses Mal habe ich müsste Parameter die passieren Referenz. Jetzt kann ich es mit einer anonymen Funktion tun und rufen Sie die f Funktion mit Parametern innerhalb der neu geschaffenen Funktion, wie solche:

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 

Aber meine Frage ist, Gibt es eine Möglichkeit, einen direkten Bezug auf das passieren f Funktion Mit Parametern zu fr, aber ohne es in einer anonymen Funktion einzuschließen?

Was muss ich fr zuweisen, um es ohne Parameter machen aufrufbaren (fr()), so dass f (1,2,3) ausgeführt wird, wenn fr aufgerufen wird?

[UPDATE] Ich folgte Jason Bunting ‚s Antwort auf here über die Teilfunktion und die JavaScript-Funktion er Beiträge es ist genau das, was ich suchte. Hier ist die Lösung:

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

Aus irgendeinem Grund hatte ich Probleme mit der ersten Anweisung (var args = Array.prototype.slice.call (Argumente) .splice (1);) und musste dies stattdessen verwenden: var args = new Array(); für (var i = 1; i

+0

nur für den Fall, dass jemand dies benötigt: 'Function.prototype.pass = function() { var args = Argumente, func = this; return function() {func.apply (this, args);} }; ' –

Antwort

77

Was Sie nach Teilfunktion Anwendung genannt wird.

Lassen Sie sich nicht von denen täuschen, die den feinen Unterschied zwischen diesem und Curry nicht verstehen, sie sind sind unterschiedlich.

Teilfunktion Anwendung kann verwendet werden, zu implementieren, aber ist nicht currying. Hier ist ein Zitat aus a blog post on the difference:

Wo Teil Anwendung eine Funktion übernimmt und daraus eine Funktion baut die weniger Argumente übernimmt, currying baut Funktionen, die durch die Zusammensetzung von Funktionen mehrere Argumente, die jeweils ein einziges Argument.

Dies wurde bereits beantwortet wurde, sehen diese Frage für Ihre Antwort: How can I pre-set arguments in JavaScript function call?

Beispiel:

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

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

Auch für die Details, diese Frage sehen.

+0

Was muss ich' fr' zuweisen, damit es ohne Parameter aufgerufen werden kann ('fr()'), so dass f (1 , 2,3) wird ausgeführt, wenn 'fr' aufgerufen wird –

+4

Hinweis für zukünftige Leser, stellen Sie sicher, dass Sie die 'partielle' Funktion von Jason in [seine andere Antwort] enthalten (http://stackoverflow.com/a/321527/ 1366033) – KyleMit

+2

Als Alternative zu Jasons "Partial" -Funktion bietet die [UnderscoreJS] (http://underscorejs.org) -Bibliothek eine '_.partial'-Funktion. – sfletche

-4

Hier finden Sie zu Ihrem zweiten Codeblock äquivalent:

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

var fr = f; 

fr(pars); 

Wenn Sie tatsächlich einen Verweis auf eine Funktion an eine andere Funktion übergeben möchten, können Sie etwas tun können:

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 

Sie sind fast sicher besser dran, ein Framework für diese Art von Dingen zu verwenden.

2

Sie auch die Funktionsprototyp überlasten:

// 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 
*/ 
Verwandte Themen