Hvordan skrive en JS funksjon som aksepterer og "forwards" variabelt antall parametre?

stemmer
6

Hvordan skriver jeg en Javascript-funksjon som godtar et variabelt antall parametre, og fremover alle disse parameterne til andre anonyme funksjoner?

For eksempel vurdere scenario av en metode som utløser en hendelse:

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

Spesielt siden jeg har en hendelse fabrikk som genererer disse fire metoder, disse metodene har ingen interesse i å vite hvor mange parametre en gitt hendelse eller dets handlers forbruker. Så jeg har det hardt fast ved 7 akkurat nå (a til g). Hvis det er noe mindre, ikke noe problem. Hvis det er noe mer, de får kuttet av. Hvordan kan jeg bare fange opp og formidle alle parametere?

Takk.

(Ved hjelp av jQuery eller annen Javascript rammeverk er ikke et alternativ her.)

Publisert på 25/10/2009 klokken 02:52
kilden bruker
På andre språk...                            


2 svar

stemmer
8

Løse dette krever kjennskap til to Javascript konsepter.

Den første er den spesielle argumentslokale variable som kan brukes til å få tilgang til funksjonsargumenter uten å vite deres navn og det fungerer som en matrise. Men argumentser ikke en Array, men er "array som" - å ha egenskaper som heter 0..n-1, hvor ner antall argumenter til funksjonen og en lengtheiendom - objekt. En enkel demonstrasjon bruk kan være:

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

Den andre funksjonen er Function.applynoe som vil aktivere en funksjon med en bestemt kontekst ( thisnår dette er nødvendig) med argumenter som følge av utvidelse av en "matrise som" objekt. Men se en .

Dermed setter det sammen:

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. Mens den ECMAScript-spesifikasjonen krever bare for en "array som" objekt, Function.apply ikke universelt arbeide med en "array som" objekt og en rekke vanlige implementeringer kreve et passende Arrayobjekt. Advarselen fra Function.applylink:

Merk: De fleste nettlesere, inkludert Chrome 14 og Internet Explorer 9 , fortsatt ikke aksepterer rekke lignende gjenstander, og vil kaste et unntak [hvis en ikke-Array objekt er passert]. [FireFox ble løst i versjon 4.]

Heldigvis finnes det et relativt enkelt uttrykk for å snu en "array som" gjenstand inn i en Array(som er ironisk fordi Array.slice ikke universelt arbeide med en "array som" objekt):

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

(Og så argskan universelt brukt i brukes Function.apply.)

Svarte 25/10/2009 kl. 03:01
kilden bruker

stemmer
5

Jeg tror "apply" og "argumenter" er to Javascript begreper du kan bruke her:

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

Her er noen kode fra min Firebug konsollen jeg prøvde ut dette med:

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');
Svarte 25/10/2009 kl. 03:04
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more