2009-03-24 13 views
138

Ich bin auf der Suche nach einem Trick zu diesem Thema. Ich weiß, wie eine dynamische, beliebige Funktion in Javascript aufrufen, bestimmte Parameter übergeben, etwa so:Aufruf der dynamischen Funktion mit dynamischen Parametern in Javascript

function mainfunc (func, par1, par2){ 
    window[func](par1, par2); 
} 

function calledfunc(par1, par2){ 
    // Do stuff here 
} 

mainfunc('calledfunc','hello','bye'); 

Ich weiß, wie optional, unbegrenzte Parameter zu übergeben Argumente [] Sammlung innerhalb mainfunc verwenden, aber ich kann nicht herausfinden, wie eine beliebige Anzahl von Parametern zu senden mainfunc an gesendet werden, genannt funf dynamisch; Wie kann ich etwas so erreichen, aber mit einer beliebigen Anzahl von optionalen Argumenten (nicht mit dem hässlichen if-else)? :

function mainfunc (func){ 
    if(arguments.length == 3) 
     window[func](arguments[1], arguments[2]); 
    elseif(arguments.length == 4) 
     window[func](arguments[1], arguments[2], arguments[3]); 
    elseif(arguments.length == 5) 
     window[func](arguments[1], arguments[2], arguments[3], arguments[4]); 
} 

function calledfunc1(par1, par2){ 
    // Do stuff here 
} 

function calledfunc2(par1, par2, par3){ 
    // Do stuff here 
} 

mainfunc('calledfunc1','hello','bye'); 
mainfunc('calledfunc2','hello','bye','goodbye'); 
+2

Das PHP-Äquivalent für 'apply()' ist 'call_u ser_func_array() '. Die http://phpjs.org/functions/call_user_func_array Lösung verwendet es auch. – powtac

Antwort

169

das Verfahren einer Funktion anwenden Verwendung: -

function mainfunc (func){ 
    window[func].apply(null, Array.prototype.slice.call(arguments, 1)); 
} 

bearbeiten: Es fällt mir ein, dass dieser mit einem leichten zwicken viel nützlicher sein würde: -

function mainfunc (func){ 
    this[func].apply(this, Array.prototype.slice.call(arguments, 1)); 
} 

Dies funktioniert außerhalb des Browsers (this ist standardmäßig der globale Speicherplatz). Der Einsatz von Call auf mainfunc würde auch: -

function target(a) { 
    alert(a) 
} 

var o = { 
    suffix: " World", 
    target: function(s) { alert(s + this.suffix); } 
}; 

mainfunc("target", "Hello"); 

mainfunc.call(o, "target", "Hello"); 
+7

schlagen Sie mich dazu :) https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Function/apply für ausführlichere Dokumentation – cobbal

+0

Danke für diesen Link Cobbal! Ich lese über (und entdecke) Anwendung Methode. – ARemesal

+0

Dies ist die am besten geeignete Lösung, aber in Argumenten wird der Name der Funktion enthalten (Argumente [0] = 'func'). Ich kann ein anderes Array mit allen Argumenten außer dem allerersten generieren und dann dieses neue Array verwenden, aber gibt es eine andere Lösung, die kein anderes Array verwendet? – ARemesal

-4

können nicht passieren Sie einfach die arguments Array zusammen?

function mainfunc (func){ 
    // remove the first argument containing the function name 
    arguments.shift(); 
    window[func].apply(null, arguments); 
} 

function calledfunc1(args){ 
    // Do stuff here 
} 

function calledfunc2(args){ 
    // Do stuff here 
} 

mainfunc('calledfunc1','hello','bye'); 
mainfunc('calledfunc2','hello','bye','goodbye'); 
+3

Nein, Sie können nicht, da "Argumente" kein Array, sondern ein Array-ähnliches Objekt ist und kein shift() -Member hat. Sie müssten die Argumente 1 in arguments.length in ein neues Array kopieren und dieses an apply() übergeben. –

13

könnten Sie .apply() verwenden

Sie benötigen einen this angeben ... Ich denke, man die this innerhalb mainfunc nutzen könnten.

function mainfunc (func) 
{ 
    var args = new Array(); 
    for (var i = 1; i < arguments.length; i++) 
     args.push(arguments[i]); 

    window[func].apply(this, args); 
} 
+0

Argumente ist kein Array und hat kein Mitglied slice(). –

+0

Hoppla, vergessen Sie das - behoben – Greg

+0

Sie müssen "Argumente" nicht in ein REAL-Array konvertieren. Was ist der Sinn darin? Es funktioniert perfekt ohne diesen Schritt ... – James

19

Ihr Code funktioniert nur für globale Funktionen, dh. Mitglieder des Objekts window. Um es mit beliebigen Funktionen zu verwenden, übergeben Sie die Funktion selbst anstelle seines Namens als String:

function dispatch(fn, args) { 
    fn = (typeof fn == "function") ? fn : window[fn]; // Allow fn to be a function object or the name of a global function 
    return fn.apply(this, args || []); // args is optional, use an empty array by default 
} 

function f1() {} 

function f2() { 
    var f = function() {}; 
    dispatch(f, [1, 2, 3]); 
} 

dispatch(f1, ["foobar"]); 
dispatch("f1", ["foobar"]); 

f2(); // calls inner-function "f" in "f2" 
dispatch("f", [1, 2, 3]); // doesn't work since "f" is local in "f2" 
+2

Das funktioniert, aber Sie sollten beachten, es wurde nicht gefragt, – Greg

12

Hier ist, was Sie brauchen:

function mainfunc(){ 
    window[Array.prototype.shift.call(arguments)].apply(null, arguments); 
} 

Das erste Argument wird als Funktionsnamen verwendet und alle die verbleibenden werden als Argumente für die aufgerufene Funktion verwendet ...

Wir können die Methode shift verwenden, um den ersten Wert aus dem Argumentenarray zurückzugeben und dann zu löschen. Beachten Sie, dass wir es vom Array-Prototyp aus aufgerufen haben, da "Argumente" streng genommen kein reales Array sind und daher die shift-Methode nicht wie ein normales Array erben.


Sie können auch die Shift-Methode wie folgt aufrufen:

[].shift.call(arguments); 
+0

Vielen Dank JimmyP, Ihre Lösung entspricht (nach der Bearbeitung) der AnthonyWJones, und Sie gaben mir tolle Tipps und Erklärungen zur Verwendung von Array. Prototyp und []. – ARemesal

+0

Seltsam, ich bin mir sicher, dass ich das versucht habe und einen Fehler in IE – Greg

3

Wenn Sie mit „Argumente“ ein paar andere weitergeben wollen, müssen Sie das Array aller Argumente zusammen schaffen, das heißtdies wie:

var Log = { 
    log: function() { 
     var args = ['myarg here']; 
     for(i=0; i<arguments.length; i++) args = args.concat(arguments[i]); 
     console.log.apply(this, args); 
    } 
} 
4

Der einfachste Weg könnte sein:

var func='myDynamicFunction_'+myHandler; 
var arg1 = 100, arg2 = 'abc'; 

window[func].apply(null,[arg1, arg2]); 

Angenommen wird, dass Zielfunktion bereits zu einem „Fenster“ Objekt angebracht.

-5

Falls jemand sucht noch dynamischen Funktionsaufruf mit dynamischen Parametern -

callFunction("aaa('hello', 'world')"); 

    function callFunction(func) { 
       try 
       { 
        eval(func); 
       } 
       catch (e) 
       { } 
      } 
    function aaa(a, b) { 
       alert(a + ' ' + b); 
      } 
+2

bekommen habe, nein, nein, nein und nein. auch Nein. – Kroltan

+0

happy debugging 10000 Zeilen davon ... wenn das Leben hart ist, warum es nicht schwieriger machen! – StefanNch

+1

Heiliger Mist, was habe ich gerade gesehen haha. –

0

Jetzt bin ich mit dieser:

Dialoglar.Confirm = function (_title, _question, callback_OK) { 
    var confirmArguments = arguments; 
    bootbox.dialog({ 
     title: "<b>" + _title + "</b>", 
     message: _question, 
     buttons: { 
      success: { 
       label: "OK", 
       className: "btn-success", 
       callback: function() { 
        if (typeof(callback_OK) == "function") {       callback_OK.apply(this,Array.prototype.slice.call(confirmArguments, 3)); 
        } 
       } 
      }, 
      danger: { 
       label: "Cancel", 
       className: "btn-danger", 
       callback: function() { 
        $(this).hide(); 
       } 
      } 
     } 
    }); 
}; 
-1
function a(a, b) { 
    return a + b 
}; 

function call_a() { 
    return a.apply(a, Array.prototype.slice.call(arguments, 0)); 
} 

console.log(call_a(1, 2)) 

Konsole: 3

Verwandte Themen