Cómo escribir una función JS que acepte y & # 8220; reenvía & # 8221; número variable de parámetros?

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

Pregunta

¿Cómo escribo una función de Javascript que acepta un número variable de parámetros y reenvía todos esos parámetros a otras funciones anónimas?

Por ejemplo, considere el escenario de un método que dispara 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,...);
    }
}

Especialmente ya que tengo una fábrica de eventos que genera estos métodos de disparo, estos métodos no tienen interés en saber cuántos parámetros consume un evento determinado o sus manejadores. Así que lo tengo cableado a las 7 en este momento (de la A a la G). Si es menos, no hay problema. Si es más, se cortan. ¿Cómo puedo capturar y pasar todos los parámetros de todos ?

Gracias.

(El uso de jQuery o cualquier otro marco de JavaScript no es una opción aquí).

¿Fue útil?

Solución

Resolver esto requiere el conocimiento de dos conceptos de JavaScript.

El primero es el argumentos argumentos es no una Array , pero es " matriz como " - tener propiedades llamadas 0..n-1 , donde n es el número de argumentos de la función y una propiedad de length - objeto . Un simple uso de demostración podría ser:

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 segunda función es Function.apply que invocará una función con un contexto específico ( este cuando se llama) con argumentos que resultan de la expansión de una matriz " como: " objeto. Pero vea 1 .

Así, juntándolo:

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 Mientras que la especificación ECMAScript solo solicita una matriz " como " objeto, Function.apply no funciona universalmente con un " matriz como " El objeto y varias implementaciones comunes requieren un objeto Array adecuado. La advertencia del enlace Function.apply :

  

Nota: La mayoría de los navegadores, incluidos Chrome 14 y Internet Explorer 9 , aún no aceptan matrices como objetos y lanzará una excepción [si no es así. Se pasa el objeto de la matriz]. [FireFox se corrigió en la versión 4]

Afortunadamente, hay un modismo relativamente simple para convertir una matriz como " objeto en un Array (lo cual es irónico porque Array.slice funciona universalmente con un " matriz como " objeto):

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

(Y, a continuación, args se puede usar universalmente como en Function.apply .)

Otros consejos

Creo que " aplica " y " argumentos " Hay dos conceptos de JavaScript que puedes usar aquí:

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

Aquí hay algo de código de mi consola Firebug. Probé esto con:

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');
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top