Übergeben Sie eine JavaScript-Funktion als Parameter

665

Wie übergebe ich eine Funktion als Parameter, ohne dass die Funktion in der "übergeordneten" Funktion ausgeführt wird oder verwendet wird eval()? (Da ich gelesen habe, dass es unsicher ist.)

Ich habe das:

addContact(entityId, refreshContactList());

Es funktioniert, aber das Problem ist, dass es refreshContactListausgelöst wird, wenn die Funktion aufgerufen wird, anstatt wenn sie in der Funktion verwendet wird.

Ich könnte es mit umgehen eval(), aber es ist nicht die beste Vorgehensweise, so wie ich es gelesen habe. Wie kann ich eine Funktion als Parameter in JavaScript übergeben?

imperium2335
quelle

Antworten:

929

Sie müssen nur die Klammern entfernen:

addContact(entityId, refreshContactList);

Dies übergibt dann die Funktion, ohne sie zuerst auszuführen.

Hier ist ein Beispiel:

function addContact(id, refreshCallback) {
    refreshCallback();
    // You can also pass arguments if you need to
    // refreshCallback(id);
}

function refreshContactList() {
    alert('Hello World');
}

addContact(1, refreshContactList);
Fenton
quelle
6
@stevefenton, erwäge, deine Antwort mit einem h2ooooooo-Kommentar zu aktualisieren, es wäre sehr nützlich.
Morgan Wilde
5
Aufgrund der Frage akzeptiert der Rückruf keine Parameter, weshalb ich sie aus dem Beispiel herausgelassen habe. Ich werde einen Kommentar dazu hinzufügen.
Fenton
4
@ Everke Es würde so aussehen ...addContact(1, function(id) { console.log(id); });
Fenton
4
@ Steve Fenton: Nachdem ich Ihre Antwort gelesen hatte, fragte ich mich, warum ich gefragt habe ... :-)
Veverke
1
Die Klassensyntax in ECMAScript hätte kein =Vorzeichen ... class myFuncs {statt class myFuncs = {. Sie müssen auch in einer Umgebung ausgeführt werden, die die Klassensyntax unterstützt (noch nicht von allen Browsern unterstützt). Wenn Sie immer noch Probleme haben, ist es möglicherweise besser für eine ganz neue Frage geeignet, da es bei Ihrem Problem nicht darum geht, Funktionen zu übergeben, sondern um die allgemeine ES-Syntax.
Fenton
336

Wenn Sie eine Funktion übergeben möchten, referenzieren Sie sie einfach mit Namen ohne Klammern:

function foo(x) {
    alert(x);
}
function bar(func) {
    func("Hello World!");
}

//alerts "Hello World!"
bar(foo);

Manchmal möchten Sie jedoch möglicherweise eine Funktion mit enthaltenen Argumenten übergeben , diese jedoch erst aufrufen, wenn der Rückruf aufgerufen wird. Um dies zu tun, verpacken Sie es beim Aufrufen einfach in eine anonyme Funktion wie folgt:

function foo(x) {
   alert(x);
}
function bar(func) {
   func();
}

//alerts "Hello World!" (from within bar AFTER being passed)
bar(function(){ foo("Hello World!") });

Wenn Sie möchten, können Sie auch die Apply- Funktion verwenden und einen dritten Parameter haben, der ein Array der Argumente ist, wie z.

function eat(food1, food2)
{
    alert("I like to eat " + food1 + " and " + food2 );
}
function myFunc(callback, args)
{
    //do stuff
    //...
    //execute callback when finished
    callback.apply(this, args);
}

//alerts "I like to eat pickles and peanut butter"
myFunc(eat, ["pickles", "peanut butter"]); 
dallin
quelle
70
Dies sollte höher eingestuft werden, da er sich auch mit der Übergabe einer Funktion mit Argumenten befasst
Deltanin
3
Und etwas , das ich diesen hinzufügen werde , ist , dass diese Funktion allein - in der Lage , JavaScript - Funktionen als Argumente oder Variablen zu übergeben oder dergleichen - ist die Funktion , die in JavaScript so mächtig und so groß Code macht.
TheHansinator
@ Compynerd255 Ich stimme zu, dies und die Fähigkeit, schnell Objektliterale zu erstellen, sind meine beiden Lieblingsaspekte von Javascript. Ich vermisse immer Objektliterale in Sprachen, die sie nicht haben.
Dallas
3
Ich bin Javascript für die Bereitstellung dieser Funktion sehr dankbar und Ihnen @dallin, dass Sie mich wissen lassen, dass sie existiert.
Dipendu Paul
Für das Beispiel "In eine anonyme Funktion einschließen" gibt die anonyme Funktion, falls dies nicht offensichtlich ist, die Funktion selbst (mit Parametern) zurück und wird aufgerufen, wenn sie die Klammer in func () erreicht. Es dauerte eine Weile, bis ich es herausgefunden hatte, also dachte ich, es könnte anderen helfen.
Hubpixel
51

Beispiel 1:

funct("z", function (x) { return x; });

function funct(a, foo){
    foo(a) // this will return a
}

Beispiel 2:

function foodemo(value){
    return 'hello '+value;
}

function funct(a, foo){
    alert(foo(a));
}

//call funct    
funct('world!',foodemo); //=> 'hello world!'

Schau dir das an

Gadde
quelle
Im ersten Beispiel sollten Sie das Schlüsselwort return wie folgt hinzufügen: function funct (a, foo) {return foo (a) // dies gibt a zurück}, sonst werden Sie undefiniert
Artem Fedotov
34

Um die Funktion als Parameter zu übergeben, entfernen Sie einfach die Klammern!

function ToBeCalled(){
  alert("I was called");
}

function iNeedParameter( paramFunc) {
   //it is a good idea to check if the parameter is actually not null
   //and that it is a function
   if (paramFunc && (typeof paramFunc == "function")) {
      paramFunc();   
   }
}

//this calls iNeedParameter and sends the other function to it
iNeedParameter(ToBeCalled); 

Die Idee dahinter ist, dass eine Funktion einer Variablen ziemlich ähnlich ist. Anstatt zu schreiben

function ToBeCalled() { /* something */ }

du könntest genauso gut schreiben

var ToBeCalledVariable = function () { /* something */ }

Es gibt jedoch geringfügige Unterschiede zwischen den beiden - beide sind gültige Methoden zum Definieren einer Funktion. Wenn Sie nun eine Funktion definieren und sie explizit einer Variablen zuweisen, erscheint es ziemlich logisch, dass Sie sie als Parameter an eine andere Funktion übergeben können und keine Klammern benötigen:

anotherFunction(ToBeCalledVariable);
Naivisten
quelle
2
Nur typeof paramFunc == "function"ist genug, denn wenn es nicht aufrufbar ist, können Sie es ignorieren.
Jimmy Knoot
16

Unter JavaScript-Programmierern gibt es einen Satz: "Eval is Evil". Versuchen Sie also, ihn um jeden Preis zu vermeiden!

Neben der Antwort von Steve Fenton können Sie Funktionen auch direkt übergeben.

function addContact(entity, refreshFn) {
    refreshFn();
}

function callAddContact() {
    addContact("entity", function() { DoThis(); });
}
Matthew Layton
quelle
8

Ich habe mir mit diesem Problem alle Haare abgeschnitten. Ich konnte die obigen Beispiele nicht zum Laufen bringen, also endete ich wie folgt:

function foo(blabla){
    var func = new Function(blabla);
    func();
}
// to call it, I just pass the js function I wanted as a string in the new one...
foo("alert('test')");

Und das funktioniert wie ein Zauber ... für das, was ich zumindest brauchte. Hoffe es könnte einigen helfen.

Fenix ​​Aoras
quelle
6

Ich schlage vor, die Parameter in ein Array einzufügen und sie dann mithilfe der .apply()Funktion aufzuteilen . Jetzt können wir eine Funktion mit vielen Parametern einfach übergeben und auf einfache Weise ausführen.

function addContact(parameters, refreshCallback) {
    refreshCallback.apply(this, parameters);
}

function refreshContactList(int, int, string) {
    alert(int + int);
    console.log(string);
}

addContact([1,2,"str"], refreshContactList); //parameters should be putted in an array
Naramsim
quelle
5

Sie können auch eval()das Gleiche tun.

//A function to call
function needToBeCalled(p1, p2)
{
    alert(p1+"="+p2);
}

//A function where needToBeCalled passed as an argument with necessary params
//Here params is comma separated string
function callAnotherFunction(aFunction, params)
{
    eval(aFunction + "("+params+")");
}

//A function Call
callAnotherFunction("needToBeCalled", "10,20");

Das ist es. Ich suchte auch nach dieser Lösung und probierte Lösungen aus, die in anderen Antworten bereitgestellt wurden, bekam sie aber schließlich anhand des obigen Beispiels zum Laufen.

Null Zeiger
quelle
2

Hier ist ein anderer Ansatz:

function a(first,second)    
{        
return (second)(first);           
}     

a('Hello',function(e){alert(e+ ' world!');}); //=> Hello world     
Cochon
quelle
2

In der Tat scheint ein bisschen kompliziert, ist nicht.

Methode als Parameter abrufen:

 function JS_method(_callBack) { 

           _callBack("called");  

        }

Sie können als Parametermethode angeben:

    JS_method(function (d) {
           //Finally this will work.
           alert(d)
    });
Hakkı Eser
quelle
1
Bitte erläutern Sie Ihre Antwort.
MillaresRoo
2

Die anderen Antworten beschreiben hervorragend, was vor sich geht, aber ein wichtiges "Gotcha" besteht darin, sicherzustellen, dass alles, was Sie durchlaufen, tatsächlich ein Verweis auf eine Funktion ist.

Wenn Sie beispielsweise eine Zeichenfolge anstelle einer Funktion durchlaufen, wird folgende Fehlermeldung angezeigt:

function function1(my_function_parameter){
    my_function_parameter();   
}

function function2(){
 alert('Hello world');   
}

function1(function2); //This will work

function1("function2"); //This breaks!

Siehe JsFiddle

Sieger
quelle
0

Manchmal, wenn Sie sich mit der Ereignisbehandlungsroutine befassen müssen, also auch das Ereignis als Argument übergeben müssen, benötigen die meisten modernen Bibliotheken wie "Reagieren" und "Winkel" dies möglicherweise.

Ich muss die OnSubmit-Funktion (Funktion aus der Bibliothek eines Drittanbieters) mit einer benutzerdefinierten Validierung für reactjs überschreiben und habe die Funktion und das Ereignis wie unten angegeben übergeben

URSPRÜNGLICH

    <button className="img-submit" type="button"  onClick=
 {onSubmit}>Upload Image</button>

MADE A NEW FUNCTION uploadund aufgerufen übergeben onSubmitund Ereignis als Argumente

<button className="img-submit" type="button"  onClick={this.upload.bind(this,event,onSubmit)}>Upload Image</button>

upload(event,fn){
  //custom codes are done here
  fn(event);
}
sumit
quelle
-3

Sie können auch einen JSON verwenden, um JS-Funktionen zu speichern und zu senden.

Überprüfe das Folgende:

var myJSON = 
{
    "myFunc1" : function (){
        alert("a");
    }, 
    "myFunc2" : function (functionParameter){
        functionParameter();
    }
}



function main(){
    myJSON.myFunc2(myJSON.myFunc1);
}

Dies wird 'a' drucken.

Folgendes hat den gleichen Effekt wie oben:

var myFunc1 = function (){
    alert('a');
}

var myFunc2 = function (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Welches ist auch der gleiche Effekt mit dem folgenden:

function myFunc1(){
    alert('a');
}


function myFunc2 (functionParameter){
    functionParameter();
}

function main(){
    myFunc2(myFunc1);
}

Und ein Objektparadigma mit Class als Objektprototyp:

function Class(){
    this.myFunc1 =  function(msg){
        alert(msg);
    }

    this.myFunc2 = function(callBackParameter){
        callBackParameter('message');
    }
}


function main(){    
    var myClass = new Class();  
    myClass.myFunc2(myClass.myFunc1);
}
Gazgas
quelle
9
Ihr Top-Codebeispiel ist nicht JSON. Dies ist ein Standard-JavaScript-Objekt. Sie können in JSON auch keine Funktionen senden / empfangen.
Matthew Layton