4

Not react specific, so hope ok to ask, but I thought the spread operator flattens an array?

So with the following sum function which sums the args, you can use .apply to pass in the values:

function sum() {
    return arguments.reduce((total, number) => total + number, 0);
}

var values = [2, 4, 8, 12, 16];

console.log(sum.apply(null, values));

I thought you could just addat the function and use the spread operator to flatten the array so call could be used. (I know you wouldn't use call in this instance, but I was just surprised as I thought the spread flattened the array:

function sum() {
    return [...arguments].reduce((total, number) => total + number, 0);
}

var values = [2, 4, 8, 12, 16];

console.log(sum.call(null, values));

This returns the string 02,4,8,12,16

Le Moi
  • 807
  • 1
  • 11
  • 33

2 Answers2

2

This happens because arguments is array-like of array. The array becomes converted to string.

As call documentation says,

While the syntax of this function is almost identical to that of apply(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments.

This should work as expected with:

sum(...values);
sum.call(null, ...values);
sum.apply(null, values);

By the way, arguments and call aren't welcome in ES6.

Estus Flask
  • 150,909
  • 47
  • 291
  • 441
  • Thanks estus. Could you briefly explain why you spread the values on the .call? If it is already a flat array, why do you spread there? Thanks for the heads up on the use of arguments and call use in ES6 - why is this? (Really appreciate the help) – Le Moi Jan 10 '17 at 10:37
  • I've updated the answer. That's the main difference between `call` and `apply`. The former accepts a list of args (which can be spread from an array). The latter accepts an array of args. – Estus Flask Jan 10 '17 at 10:43
  • Yep, got that - thanks estus, was just interested in why call and arguments aren't used in ES6? – Le Moi Jan 10 '17 at 10:45
  • `arguments` are conveniently replaced with `...args` rest param. And `call` with `null` context is replaced with spread argument. – Estus Flask Jan 10 '17 at 10:45
  • Also, `arguments` can't be used in arrow functions. – Estus Flask Jan 10 '17 at 10:47
1

The arguments is an array like structure so while passing the array as an argument the structure would be like a nested array. So applying spread operator results an array in the format [[2, 4, 8, 12, 16]](i.e, [...[[2, 4, 8, 12, 16]]]) and the reduce method apply 0 + [2, 4, 8, 12, 16] and which results "02,4,8,12,16".

To make it work you need to pass the array values as arguments using Function#apply or get the first argument.

function sum() {
  return [...arguments].reduce((total, number) => total + number, 0);
}

var values = [2, 4, 8, 12, 16];

console.log(sum.apply(null, values));

function sum() {
  return [...arguments][0].reduce((total, number) => total + number, 0);
}

var values = [2, 4, 8, 12, 16];

console.log(sum.call(null, values));

Refer : What is the difference between call and apply?

Community
  • 1
  • 1
Pranav C Balan
  • 106,305
  • 21
  • 136
  • 157
  • Thanks Pranav, but why does the array of number become a string? With the .call instance, why is the arguments not still an array of numbers? – Le Moi Jan 10 '17 at 10:23
  • Also, this returns NaN – Le Moi Jan 10 '17 at 10:24
  • @LeMoi : you need to use `apply` for passing array of elements as argument .... `console.log(sum.apply(null, values));` – Pranav C Balan Jan 10 '17 at 10:27
  • @LeMoi : check the snippet – Pranav C Balan Jan 10 '17 at 10:28
  • Yeah I know this is a bad example, just was trying to understand why the spread operator didn't flatten the array, so if I log arguments in the sum function using .call, the arguments is a nested array with all the numbers. – Le Moi Jan 10 '17 at 10:28
  • @LeMoi `arguments` is an array like structure... while passing array as an argument....`arguments` would contain nested array..... ie, using spread operator `[[array]]` => `[array]` – Pranav C Balan Jan 10 '17 at 10:30
  • Thanks Pranav - that is what I thought, but what I wasn't sure on is why [...arguments] didn't spread the array into a flattened array. Sorry if I am not making sense. – Le Moi Jan 10 '17 at 10:39
  • @LeMoi : it's actually expanding `i.e, [...[[2, 4, 8, 12, 16]]] ===> [[2, 4, 8, 12, 16]]` – Pranav C Balan Jan 10 '17 at 10:40