6

I'm trying to turn arguments variable which is accessible inside function into an array. I've tried two ways:

Array.prototype.splice.apply(arguments, 0) //fails
Array.prototype.splice.call(arguments, 0) //return array

Can you please guys elaborate on why the first option fails while the second one succeeds?

Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • 14
    The second argument to `.apply()` should be an array, like `[0]`. – Pointy Jul 29 '14 at 13:54
  • 2
    That is, in fact, the main difference between `call` and `apply`. – Andy Jul 29 '14 at 13:55
  • Indeed, so `Array.prototype.splice.apply(arguments, [0])` should work. `apply()` and `call()` are not the same! – Jeroen Noten Jul 29 '14 at 13:56
  • The error message `Function.prototype.apply: argumentsArray is not an array-like object` (or something along the lines of this) should be clear enough, or at least tell you to [check the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply) – Bergi Jul 29 '14 at 14:04
  • Because http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.3 – dfsq Jul 29 '14 at 14:04
  • @Pointy, thanks, can you make your comment an answer so that I mark it as the answer? – Max Koretskyi Jul 29 '14 at 14:07

1 Answers1

7

That's because Array.prototype.splice.apply(arguments, 0) is (roughly) equivalent to arguments.splice([0]), as it has been said by others before me, apply expects an Array as its second argument. If you wanted to retrieve the n-first parameters, you could do Array.prototype.splice.apply(arguments, [0,n]) which would be (roughly) equivalent to arguments.splice.(0,n).

On the contrary, call works with any type of parameters. Array.prototype.splice.call(arguments, 0) is (roughly) equivalent to arguments.splice(0), and since splice expects an integer as its first argument and not an array, the second solution works (but not the first one). Thus, Array.prototype.splice.apply(arguments, [0]) would also work as Jeroen Noten suggested it.

Please note that the "equivalences" I'm referring to would not actually work since arguments is not an Array but rather an Array-like object.

However, the technique you mentioned is frequently used to turn an Array-like object into a proper Array.

EDIT : I edited my answer as it contained a big mistake. Thanks to cookiemonster for the correction.

Waldo Jeffers
  • 2,289
  • 1
  • 15
  • 19
  • Did you read what I wrote ? oO – Waldo Jeffers Jul 29 '14 at 14:04
  • Yes I did. The lack of equivalence has nothing to do with `arguments` being Array-like. – cookie monster Jul 29 '14 at 14:05
  • 1
    Like cookiemonster said, it's not the `splice` that fails. – Bergi Jul 29 '14 at 14:05
  • 1
    Oohhh my bad, you're absolutely right @cookiemonster. Apologies. I'll edit my answer. – Waldo Jeffers Jul 29 '14 at 14:07
  • Hmmm, are you sure ? I just tried on JSFiddle and got "TypeError: arguments.splice is not a function". – Waldo Jeffers Jul 29 '14 at 14:17
  • 1
    Ah, I missed what you meant. I thought you were referring to the former (`.call`, `.apply`) as the equivalent. For a direct call, the method would need to be placed directly on the `arguments` object. – cookie monster Jul 29 '14 at 14:19
  • Ahh. No, I just meant that *since* `arguments` is an Array-like object, we *have to* use the `Array.prototype.call|apply(arguments,...)` syntax to turn it into a proper array. But you're right, this technique is only possible *because* `arguments` *is* an Array-like object. Quiproquo :p I hope all is clear now :) – Waldo Jeffers Jul 29 '14 at 14:22