How to write a JS function that receives and "forwards" a variable number of parameters?

How to write a Javascript function that takes a variable number of parameters and forwards all these parameters to other anonymous functions?

For example, consider a script for a method that fires an event:

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

Moreover, I have a factory event that generates these fire methods, these methods are not interested in knowing how many parameters this event or its handlers consumes. So I have this hard connection in 7 right now (via g). If it is less, no problem. If this is not the case, they are cut off. How can I just capture and pass all parameters?

Thanks.

(Using jQuery or any other Javascript structure is not an option here).

+6
javascript arguments apply variadic-functions
source share
2 answers

Solving this requires knowledge of two JavaScript concepts.

The first is a special arguments local variable that can be used to access function arguments without knowing their name, and works like an array. However, arguments not Array , but it is "array like" - it has properties with the name 0..n-1 , where n is the number of function arguments and the length property object. A simple use of the demo could be:

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

The second feature is Function.apply , which will call a function with a specific context ( this when it is called) with arguments that arise due to the expansion of an object of type array. But see 1 .

Thus, connecting it:

 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 While the ECMAScript specification calls only an array object, Function.apply does not work everywhere with an array object, and a number of common implementations require a proper Array object. Warning from Function.apply link:

Note. Most browsers, including Chrome 14 and Internet Explorer 9, still do not accept array-type objects and throw an exception [if the object is passed without an array]. [FireFox has been fixed in version 4.]

Fortunately, there is a relatively simple idiom to turn an array object into an Array (which is ironic because Array.slice works everywhere with an object of type array):

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

(And then args can be used universally in Function.apply .)

+8
source share

I think that “apply” and “arguments” are two JavaScript concepts that you can use here:

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

Here is some code from my Firebug console I tried this:

 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'); 
+5
source share

All Articles