2009-10-25 18 views
6

Comment écrire une fonction Javascript qui accepte un nombre variable de paramètres et transférer tous ces paramètres à d'autres fonctions anonymes?Comment écrire une fonction JS qui accepte et "transmet" un nombre variable de paramètres?

Par exemple, considérons le scénario d'une méthode qui déclenche un événement:

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,...); 
    } 
} 

D'autant plus que j'ai une fabrique d'événements qui génère ces méthodes d'incendie, ces méthodes ont aucun intérêt à savoir combien de paramètres a donné événement ou ses gestionnaires mangent. Donc je l'ai câblé à 7 maintenant (a à g). Si c'est moins, pas de problème. Si c'est plus, ils sont coupés. Comment puis-je simplement capturer et transmettre tous les paramètres?

Merci.

(En utilisant jQuery ou tout autre framework Javascript est pas une option ici.)

+0

Est-il possible de passer des paramètres comme un tableau en JavaScript? Cela pourrait le faire. – Cyclone

Répondre

8

La résolution de ce nécessite la connaissance des deux concepts JavaScript.

La première est la variable locale spéciale arguments qui peut être utilisée pour accéder aux arguments de la fonction sans connaître leur nom et fonctionne comme un tableau. Cependant, arguments est pas un Array, mais est « tableau comme » - ayant des propriétés nommées 0..n-1, où n est le nombre d'arguments à la fonction et une length propriété - objet. Une simple utilisation de démonstration pourrait être:

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") 

La deuxième caractéristique est Function.apply qui invoquera une fonction avec un contexte spécifique (this lorsqu'elle est appelée) avec des arguments qui résultent de l'expansion d'un « tableau comme » objet. Mais voir.

Ainsi, mettre ensemble:

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) 
    } 
} 

Alors que la spécification ECMAScript appelle uniquement pour un "tableau comme" objet, Function.applyne travailler universellement avec un "tableau comme" objet et un certain nombre d'implémentations communes exigent un objet Array approprié. L'avertissement du Function.apply lien:

Note: La plupart des navigateurs, y compris Chrome 14 et Internet Explorer 9, ne sont toujours pas accepter tableau comme des objets et jetteront une exception [si un objet non-Array est passé]. [FireFox a été corrigé dans la version 4.]

Heureusement, il y a un langage relativement simple de transformer un « tableau comme » objet dans un Array (ce qui est ironique, car Array.slicene fonctionne universellement avec un objet « tableau comme »):

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

(et puis args peut être universellement utilisé dans être utilisé dans Function.apply.)

+0

ne semble pas s'appliquer à ce que le demandeur veut. – mauris

+5

Je pense que c'est * exactement * ce que le demandeur veut. – bcat

+0

Merci, pst. Le document que vous liez est excellent. J'ai été déchiré entre marquer la vôtre ou la réponse de Lauri comme la réponse acceptée parce qu'il a pris le temps de l'appliquer à ma question initiale. C'était un tirage au sort. J'espère que tu comprends. –

5

Je pense que « appliquer » et « arguments » sont deux concepts JavaScript vous pouvez utiliser ici:

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

est Voici une partie de ma console Firebug J'ai essayé avec:

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

Ce code est incorrect. arguments est semblable à un tableau. Ce n'est pas "un tableau". apply prend un tableau en tant que second paramètre. –

+0

pst, cela semble marcher pour moi, en ce que la méthode invoquée using apply (null, arguments) est appelée et semble reconnaître tous les arguments distincts. Y a-t-il un problème qui me manque? –

+0

@pst - Je ne le savais pas - avez-vous un exemple où la fonction que j'ai posté ne fonctionne pas? –