Please explain JavaScript 'arguments' vs '...arguments'

I’m struggling to understand the difference between [arguments] and […arguments], as below.

    return [...arguments];
}```
and 
```function foo(arr){
    return [arguments];
}```
The above seem to yield the same output to my console, but not in the example below, the two expressions give different results

``` function uniteUnique(arr){
    let output = [];
    let newArr = [...arguments];
    for(let i = 0; i < newArr.length; i ++){
      for(let j = 0; j < newArr[i].length; j ++){
        if(!output.includes(newArr[i][j]))
        output.push(newArr[i][j]);
      }
    }
    return output;
    
    
  }```

arguments comes as a array-look like list.

So [arguments] is kind of like [[1,2,3,4]].
But […arguments] is using a spread operator. Basically it’s extracting out values from array-like arguments and listing as values separated as commas. So …arguments will be something like 1, 2, 3, 4. So […arguments] is basically making array like list into an array.

1 Like

That helps, thank you…Is it right to say that foo = [arguments] will preserve the formatting of the arguments but foo = […arguments] will not?

Well, yes in a way. But there is really no reason for you to do foo = [arguments] this. You are just encapsulating array like thing inside of an array.

I would go with foo = […arguments].

1 Like

The spread operator ... is kinda hard to explain in words, it’s effectively the same as doing this (the code inside the function is the important bit):

function argsAsArray() {
  const arrayOfArgs = [];
  for (let i = 0; i < arguments.length; i++) {
    arrayOfArguments.push(arguments[i]);
  }
  return arrayOfArguments;
}

So argsAsArray(1) will return [1], argsAsArray(1,2,3) is [1,2,3] and so on.


So arguments is a thing that’s like an array, but it isn’t, and to use array methods on it, it needs to be converted into a real array. The above code does that. The spread operator + an array works exactly like the code in the function above:

function argsAsArray() {
  return [... arguments];
}

You are saying “put the elements in arguments into an array, one by one, in order”. It works with any object that is iterable (arrays, strings, maps, sets, arguments, nodelists, etc), example:

const str = 'hello';
// put the elements in str into an array, in order:
const strArr = [...str]
// strArr is ['h', 'e', 'l', 'l', 'o']

If you do [arguments], you are just putting a single object (arguments) into an array — not the values from it, the whole thing — so it ends up a bit like [{'0': 'arg1', '1': 'arg2', length: 2}]

2 Likes

Excellent explanation! Thanks.

Makes sense:grinning: