Reputation: 67
I have this function
var foo = function(){
var args = Array.prototype.slice.call(arguments, 0);
for (var i = 0; i < args.length; i++) {
console.log(args[i]);
}
};
that's used like this
foo(1, 2, 3, 4, 5, 6, 7, 8);
It's outcome
But I want it's usage to work like this, and get the same outcome
foo(1, 2, foo(3, 4, 5), 6, 7, 8);
Yet the out come for this is
Thanks in advance
Mach
Upvotes: 0
Views: 56
Reputation: 1075059
But I want it's usage to work like this, and get the same outcome
foo(1, 2, foo(3, 4, 5), 6, 7, 8);
You can't. That line is equivalent to this:
var tmp = foo(3, 4, 5);
foo(1, 2, tmp, 6, 7, 8);
That is, first the foo(3, 4, 5)
bit runs, and then the foo(1, 2, mumble, 6, 7, 8)
bit runs.
There are games you can play to defer execution, but they will tend to be very specific to what you're actually doing (which I assume isn't just outputting numbers in order).
For instance, a game you could play here would be to have foo
detect whether its arguments are functions and, if so, call them; then you could use Function#bind
(or similar) to create functions that, when called, will have the arguments you want. That looks like this:
var foo = function(){
var args = Array.prototype.slice.call(arguments, 0);
var arg;
for (var i = 0; i < args.length; i++) {
arg = args[i];
if (typeof arg === "function") {
arg();
} else {
console.log(arg);
}
}
};
and then used like this:
foo(1, 2, foo.bind(undefined, 3, 4, 5), 6, 7, 8);
That works because Function#bind
doesn't call the function, it creates a new function that, when called, will get called with the arguments you gave bind
(the first argument is what this
will be during the call; if you don't have anything specific it needs to be, use undefined
or null
). So in effect when we do this:
foo(1, 2, foo.bind(undefined, 3, 4, 5), 6, 7, 8);
...we're doing this:
var tmpFunction = foo.bind(undefined, 3, 4, 5);
foo(1, 2, tmpFunction, 6, 7, 8);
(Function#bind
is an ES5 feature present in all modern browsers except IE8 (which while not "modern" is still in significant use), but it can be correctly "shimmed" using es5-shim or similiar.)
(Trivia: This thing where you create a function with some of its arguments "baked into" it is called currying a function, so named after the mathematician Haskell Curry. [And yes, that's where the programming language Haskell gets its name.])
Upvotes: 3
Reputation: 2129
First you have to return the args in your foo() as so:
var foo = function(){
var args = Array.prototype.slice.call(arguments, 0);
for (var i = 0; i < args.length; i++) {
console.log(args[i]);
}
return args;
};
But, even so you would get an Array as the 3rd element of your array when you call:
foo(1, 2, foo(3, 4, 5), 6, 7, 8);
You will have to filter your arguments so if there's an array found among your arguments, you should split that into scalars and then pass them to the slice method.
Hope this helped, keep me posted.
Upvotes: 0
Reputation: 2975
You're calling foo(3,4,5) and putting it's return value to the second call to foo(...). Your code can be written as:
var ret = foo(3,4,5);
foo(1, 2, ret, 6, 7, 8);
I am unaware what console.log accepts as arguments, but if it can handle a function, you could do:
var func = function() { foo(3, 4, 5); };
foo(1, 2, func, 6, 7, 8);
Upvotes: 0