5

I am calling a method using apply and I do not know how many arguments I will be passing:

At the moment my code looks like this:

selectFolder: function(e){
  e.preventDefault();

  this.addSelectedClass.apply(this, Array.prototype.slice.call(arguments));
},

The only reason I am using Array.prototype.slice is because it is in most examples.

Why would I not just pass arguments like this:

 this.addSelectedClass.apply(this, arguments);

2 Answers 2

6

arguments with apply() are fine

When calling apply on a function it's ok to just use original arguments. SO in your example you can easily replace the line with this one:

this.addSelectedClass.apply(this, arguments);

arguments with call() are not fine

But if you'd be calling call then you should convert arguments to an actual array (which is done by a slice() call) if you'd want to pass your function an array of arbitrary objects/values. That's why call() is usually used when you know exactly the number of arguments you'd want to pass and pass them individually.

arguments are not an actual array object. They seem to be (have length property for instance), but they're not.

Arguments on Mozilla Deveveloper Network

A bit of explanation to make it completely clear

Documentation related to apply() and call() looks like this:

func.apply(thisArg[, argsArray]);
func.call(thisArg[, arg1[, arg2[, ...]]]);

We may execute the same function using any of these.

  1. When using apply() we can pass all arguments at once. slice() is usually used to omit a particular argument from the call or to convert arguments to actual array.

  2. When using call() we pass individual arguments and as many as we need to. If we'd provide arguments converted to an array, our called function would get one parameter of type array with all arguments supplied in that particular array.

I hope this clears thing up even more.

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

4 Comments

.call() accepts a list of arguments, not an array. .apply() accepts an array.
@MisterJack, apply can take any "array-like" object, e.g.: (function (a, b) { return a+b; }).apply(this, {0:5, 1:10, length:2}); // 15
What I meant is that call should be used as foo.call(this, 'aa', 2) (a list) and not like foo.call(this, ['aa', 2]) because with a declaration like function foo(a, b) {} the latter example will have an array as the first parameter, and undefined as the second parameter.
@MisterJack: You're of course correct. I edited my answer to make it completely clear that you can still provide arguments as an array to call() but the function would get them as a single argument of type array. That's what the confusion related to your comment was all about. Hence I added more information to make it more clear.
3

Because arguments is not an array. Running Array.prototype.slice makes it a normal array with functions like map and forEach. Basically anything in Array.prototype. arguments is, without this, just an object with a length property.

In your particular case, passing just arguments would probably work.

1 Comment

i think you meant "because arguments is not an array"

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.