5

My JavaScript code is barely an Ajax request that expects XML to be returned from back-end. The back-end can return execute_callback as one of XML tags like this:

<?xml version="1.0" encoding="windows-1251"?>
<response>
    <execute_callback>
        <function_name>someFunction</function_name>
    </execute_callback>
</response>

And everything is okay as far as you know the exact number of parameters this callback expects. But what if the back-end has returned

<?xml version="1.0" encoding="windows-1251"?>
<response>
    <execute_callback>
        <function_name>someFunction</function_name>
        <param>10.2</param>
        <param>some_text</param>
    </execute_callback>
    <execute_callback>
        <function_name>otherFunction</function_name>
        <param>{ x: 1, y: 2 }</param>
    </execute_callback>
</response>

How do I now pass parameters 10.2 and 'some_text' to someFunction and JSON { x: 1, y: 2 } to otherFunction?

I know an ugly solution (using function's arguments), but I am looking for a pretty one.

And before I forget: don't parse the XML for me - I can do that on my own :) All I need is somewhat of a trick to pass an arbitrary number of arguments to a function in JavaScript. If you know Python, I want:

def somefunc(x, y):
    print x, y
args = { 'x' : 1, 'y' : 2 }
somefunc(**args)

but in JavaScript.

2
  • How do you tell the difference between a literal—such as 10.2 and "some text" — and an expression that needs to be evaluated, such as { x: 1, y: 2 }? Commented Jul 21, 2011 at 1:47
  • @RobG this does not concerns question. Example is always just an example. First thought: I will pass type attribute to <param>. It's not a problem at all to understand what type is returned. Commented Jul 21, 2011 at 3:31

4 Answers 4

9

You can just pass them all into your function:

function someFunction(){
    for(i = 0; i < arguments.length; i++)
        alert(arguments[i]);
}

Javascript functions have an arguments array-like object, and it is syntactically correct to call a javascript function with any number of arguments.

someFunction(1, 2, 'test', ['test', 'array'], 5, 0);

is a valid call to that function.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh haha, I don't think it's that ugly :)
Arguments is not an array, it's an arguments object.
6

You could refer to Function.apply. Assuming the callback functions are declared in global object (window in browser).

var callback_function = window[function_name];
if (callback_function) { // prevent from calling undefined functions
    callback_function.apply(window, params);  // params is an array holding all parameters
}

2 Comments

+1 - I think this is the best method, though likely should be protected by if (window[function_name]).... But how to tell literals from identifiers and expressions? I guess they are all passed as strings and the called function works it out.
Perfect. Exactly what I'm looking for. By the way, I prefer if (typeof fn == 'function') {
0

Instead of calling the function, reference your function as an element in an associative array by name:

var funcName = // parse your xml for function name
var params = new Array();
params[0] = 10.2; // from your parsed xml
params[1] = 'some text'; // also from your parsed xml

// functions are attached to some Object o:

o[funcName](params); // equivalent to o.funcName(params);

I wrote an example of the above here: http://jsbin.com/ewuqur/2/edit

7 Comments

function somefunc(x,y) { alert(x+y); } I want to pass ['a', 'b']. somefunc.apply(window, ['a', 'b']) -> "ab". window['somefunc'](['a','b']) -> "abundefined". Odd :-(
@Nemoden: That's not what I said to do. apply is not necessary. jsbin.com/ewuqur/2/edit
to use Function.apply is yet another approach and it works. I just compared it with your method which has produced unexpected result.
@Nemoden, your second example didn't work either. Why attach your functions to the global window object? It's a poor practice. I attach my functions to my own objects and limit scope and access through closures.
Sorry, I messed up with the code there. Just replace window['somefunc'](['a','b']) with somefunc.apply(window, ['a', 'b']). I don't see any reason why I shouldn't attach my javascript functions to window object, except you've called it "poor practice", which I can't understand why, so I still don't consider it a strong reason. Why checkEmail(str) function, which validates is a string an email, for example, should be attached to some object, but not window?
|
0

2022 Answer: You can now (Firefox=2012, Chrome=2015, Safari=2016) do this with a rest parameter:

function someFunction(first, ...extra) {
    console.log(`You started with "${first}"`);
    extra.forEach(arg => console.log(arg));
}

someFunction(1, 2, 3);

As noted in Paul's answer, there's an implicit arguments object, but arguments has some limitations. Notably, arguments contains all arguments and isn't a real array while rest parameters are a true array and intentionally omit any previously named arguments. The above example uses Array.prototype.forEach(), which won't work on arguments.

See also spread syntax, introduced at the same time, for other uses of this dot-dot-dot-variable notation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.