I got stumped by this weirdness.
Let's say I have this array:
var array = [{
something: 'special'
}, 'and', 'a', 'bunch', 'of', 'parameters'];
Could I apply
the apply
method of a function to invoke the function with the this
object being {something: 'special'}
and the parameters being the rest of array
?
In other words, could I do this
var tester = function() {
console.log('this,', this);
console.log('args,', arguments);
};
tester.apply.apply(tester, array);
And expect the output to be the following?
> this, {"something": "special"}
> args, {"0": "and", "1": "a", "2": "bunch", "3": "of", "4": "parameters"}
I tried it.
TypeError: Function.prototype.apply: Arguments list has wrong type
But why? It seems like this should work.
I got stumped by this weirdness.
Let's say I have this array:
var array = [{
something: 'special'
}, 'and', 'a', 'bunch', 'of', 'parameters'];
Could I apply
the apply
method of a function to invoke the function with the this
object being {something: 'special'}
and the parameters being the rest of array
?
In other words, could I do this
var tester = function() {
console.log('this,', this);
console.log('args,', arguments);
};
tester.apply.apply(tester, array);
And expect the output to be the following?
> this, {"something": "special"}
> args, {"0": "and", "1": "a", "2": "bunch", "3": "of", "4": "parameters"}
I tried it.
TypeError: Function.prototype.apply: Arguments list has wrong type
But why? It seems like this should work.
Share Improve this question asked Jul 16, 2013 at 20:41 skeggseskeggse 6,34311 gold badges58 silver badges82 bronze badges 3- tester.apply(tester, array); is what you want... – dandavis Commented Jul 16, 2013 at 20:46
-
2
@dandavis Not really. The value of
this
should bearray[0]
, and the arguments passed should bearray[1]
toarray[len-1]
– Ian Commented Jul 16, 2013 at 20:47 - @Ian: sorry, misunderstood. eval.call.apply(tester, array) works, since you want to apply the call (confused yet, heh).. – dandavis Commented Jul 16, 2013 at 20:49
2 Answers
Reset to default 11But why?
Let's reduce your calls step-by-step:
tester.apply.apply(tester, array) // resolves to
(Function.prototype.apply).apply(tester, array) // does a
tester.apply({something: 'special'}, 'and', 'a', 'bunch', 'of', 'parameters');
Here you can see what's going wrong. Correct would be
var array = [
{something: 'special'},
['and', 'a', 'bunch', 'of', 'parameters']
];
then the apply.apply(tester, array)
would bee
tester.apply({something: 'special'}, ['and', 'a', 'bunch', 'of', 'parameters']);
which does a
tester.call({something: 'special'}, 'and', 'a', 'bunch', 'of', 'parameters');
So with your original array
you'd need to use
(Function.prototype.call).apply(tester, array)
The apply method takes one argument for the this
context and one argument for the arguments, that you want to apply. The second argument must be an array.
tester.apply.apply(tester, array);
Due to the second apply method, the first will be called like this:
tester.apply({something: 'special'}, 'and', 'a', 'bunch', 'of', 'parameters');
And since 'and' is not an array, you get the TypeError that you described. You can easily fix this by using the call
method:
tester.call.apply(tester, array);
call
will take individual arguments instead of an array, which will result in the desired oute.