Come scrivere una funzione JS che accetta e & # 8220; inoltra & # 8221; numero variabile di parametri?

StackOverflow https://stackoverflow.com/questions/1619850

Domanda

Come posso scrivere una funzione Javascript che accetta un numero variabile di parametri e inoltra tutti quei parametri ad altre funzioni anonime?

Ad esempio, considera lo scenario di un metodo che genera un evento:

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

Soprattutto dal momento che ho una fabbrica di eventi che genera questi metodi di fuoco, questi metodi non hanno interesse a sapere quanti parametri consumano un determinato evento o i suoi gestori. Quindi l'ho cablato a 7 in questo momento (da a a g). Se è inferiore, nessun problema. Se è più, vengono tagliati. Come posso semplicemente catturare e trasmettere tutti i parametri?

Grazie.

(L'uso di jQuery o di qualsiasi altro framework Javascript non è un'opzione qui.)

È stato utile?

Soluzione

Risolvere questo richiede la conoscenza di due concetti JavaScript.

Il primo è lo speciale argomenti variabile locale che può essere utilizzata per accedere agli argomenti della funzione senza conoscerne il nome e funziona come una matrice. Tuttavia, argomenti non è non un array , ma è " array come " - con proprietà denominate 0..n-1 , dove n è il numero di argomenti della funzione e una proprietà length - oggetto . Un semplice uso dimostrativo potrebbe essere:

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 seconda funzione è Function.apply che invocherà una funzione con un contesto specifico ( this quando viene chiamato) con argomenti che derivano dalla espansione di una matrice " come " oggetto. Ma vedi 1 .

Quindi, mettendolo insieme:

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

1 Mentre la specifica ECMAScript richiede solo un array " come " object, Function.apply non funziona universalmente con un array " come " oggetto e una serie di implementazioni comuni richiedono un oggetto Array corretto. L'avviso dal link Function.apply :

  

Nota: La maggior parte dei browser, tra cui Chrome 14 e Internet Explorer 9 , non accetta ancora array come oggetti e genererà un'eccezione [se non L'oggetto array è passato]. [FireFox è stato corretto nella versione 4.]

Per fortuna, esiste un linguaggio relativamente semplice per trasformare un array "quotato come" oggetto in un Array (che è ironico perché Array.slice funziona universalmente con un array " come " oggetto):

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

(E quindi args può essere universalmente usato per essere utilizzato in Function.apply .)

Altri suggerimenti

Penso che " applica " e "argomenti" sono due concetti JavaScript che puoi usare qui:

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

Ecco un po 'di codice dalla mia console Firebug con cui l'ho provato:

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');
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top