2009-10-25 9 views
6

Wie schreibe ich eine Javascript-Funktion, die eine variable Anzahl von Parametern akzeptiert und alle diese Parameter an andere anonyme Funktionen weiterleitet?Wie schreibe ich eine JS-Funktion, die eine variable Anzahl von Parametern akzeptiert und "weiterleitet"?

Zum Beispiel das Szenario einer Methode, die ein neues Ereignis ausgelöst:

function fireStartedEvent(a,b,c,d,e,f,g,...) { 
    for(var i = 0; i < startedListeners.length; i++) { 
     startedListeners[i](a,b,c,d,e,f,g,...); 
    } 
} 

Vor allem, da ich ein Ereignis Fabrik haben, die diese Feuer Methoden erzeugt haben diese Verfahren kein Interesse zu wissen, wie viele Parameter einer gegebenen Ereignis oder seine Handler konsumieren. Also habe ich es jetzt bei 7 fest verdrahtet (a bis g). Wenn es weniger ist, kein Problem. Wenn es noch mehr ist, werden sie abgeschnitten. Wie kann ich nur alle Parameter erfassen und weitergeben?

Danke.

(Mit jQuery oder anderen Rahmen Javascript ist keine Option hier.)

+0

Ist es möglich, Parameter als ein Array in JavaScript zu übergeben? Das könnte es tun. – Cyclone

Antwort

8

Lösung dies erfordert die Kenntnis von zwei JavaScript-Konzepten.

Die erste ist die spezielle arguments lokale Variable, die verwendet werden kann, um auf die Funktionsargumente zuzugreifen, ohne ihren Namen zu kennen, und es funktioniert wie ein Array. Allerdings arguments ist nicht ein Array, sondern ist „Array wie“ - mit Eigenschaften 0..n-1 benannt, wobei n die Anzahl der Argumente für die Funktion ist und ein length Eigenschaft - Objekt. Eine einfache Demonstration Nutzung könnte sein:

function f (a) { // can include names still, if desired 
    // arguments instanceof Array -> false (exceptions to this?) 
    var firstArg = arguments[0] 
    // a === firstArg -> always true 
    // iterate all arguments, just as if it were an Array: 
    for (var i = 0; i < arguments.length; i++) { 
     alert(i + " : " + arguments[i]) 
    } 
} 
f("a","b","c") 

Das zweite Merkmal ist Function.apply, die eine Funktion mit einem bestimmten Kontext aufruft (this wenn sie aufgerufen wird) mit Argumenten, die eines „Array wie“ aus der Expansion führen Objekt. Aber siehe.

So legt es zusammen:

function fireStartedEvent() { 
    for(var i = 0; i < startedListeners.length; i++) { 
     // jQuery will often pass in "cute" things, such as a element clicked 
     // as the context. here we just pass through the current context, `this`, 
     // as well as the arguments we received. 
     var arg = Array.prototype.slice.call(arguments) 
     startedListeners[i].apply(this, args) 
    } 
} 

Während die ECMAScript-Spezifikation fordert nur für einen "Array wie" Objekt, Function.applynicht allgemein mit einem "wie Array" arbeiten Objekt und eine Reihe von gängigen Implementierungen erfordern eine ordnungsgemäße Array Objekt. Die Warnung des Function.apply Link:

Hinweis: Die meisten Browser, einschließlich Chrome 14 und Internet Explorer 9, immer noch nicht akzeptieren Array wie Objekte und eine Ausnahme [wenn ein Nicht-Array-Objekt werfen ist bestanden]. [FireFox wurde in Version 4 behoben.

]

Glücklicherweise gibt es eine relativ einfache Form ist eine „Array wie“ Objekt in ein Array zu drehen (was paradox ist, weil Array.sliceist universell mit einem „Array wie“ Arbeitsobjekt):

var args = Array.prototype.slice.call(arguments); 

(und dann args universell in in Function.apply verwendet werden, verwendet werden.)

+0

scheint nicht zu gelten, was der Fragesteller will. – mauris

+5

Ich denke das ist * genau * was der Fragesteller will. – bcat

+0

Danke, pst. Das Dokument, zu dem Sie verlinken, ist ausgezeichnet. Ich war hin- und hergerissen zwischen der Markierung deiner oder Lauris Antwort als die akzeptierte Antwort, weil er sich die Zeit genommen hat, sie auf meine ursprüngliche Frage anzuwenden. Es war ein Münzwurf. Ich hoffe, Sie verstehen. –

5

ich denke, „anwenden“ und „Argumente“ sind zwei JavaScript-Konzepte können Sie hier verwenden:

function fireStartedEvent() { 
    for (var i = 0; i < startedListeners.length; i++) { 
    startedListeners[i].apply(startedListeners[i], arguments); 
    } 
} 

Hier einige Code aus meiner Firebug-Konsole ich das ausprobiert mit:

a = function(foo) { alert('a: ' + foo); }; 
b = function(foo, bar) { alert('b: ' + foo + ', ' + bar); }; 

startedListeners = [a, b]; 

function fireStartedEvent() { 
    for (var i = 0; i < startedListeners.length; i++) { 
    startedListeners[i].apply(startedListeners[i], arguments); 
    } 
} 


fireStartedEvent('one', 'two'); 
+0

Dieser Code ist nicht korrekt. Argumente sind Array-ähnlich. Es ist kein "Array". apply verwendet ein Array als zweiten Parameter. –

+0

pst, scheint es für mich zu funktionieren, in dem die Methode aufgerufen wird mit apply (null, Argumente) aufgerufen wird und scheint alle verschiedenen Argumente zu erkennen. Gibt es ein Problem, das ich vermisse? –

+0

@pst - Ich wusste das nicht - haben Sie ein Beispiel, wo die Funktion, die ich gepostet habe, nicht funktioniert? –

Verwandte Themen