0

This snippet of JavaScript code alerts 1 as answer. Can anyone please explain how this code executes?

const b = [1,2,3];
const f = (a, ...b) => a+b;
alert( f( 1 ) );
Dai
158k31 gold badges314 silver badges438 bronze badges
asked Aug 19, 2018 at 15:56
4
  • 2
    What else would you have expected? You might want to log the value of b inside the function f. Commented Aug 19, 2018 at 15:58
  • 1
    The b on the const f = line represents a new parameter in the lambda's scope, it does not refer to the [1,2,3] array declared in the parent scope. When f(1) is invoked it does not bind a value to the variadic parameter b so its value is an empty array and 1 + [] === "1" in Javascript, hence your output value. Commented Aug 19, 2018 at 16:01
  • Also note that ... isn't an operator (neither when used for spread or, as above, for rest). And can't be, operators can't do what either spread or rest do. Commented Aug 19, 2018 at 16:02
  • 1
    See stackoverflow.com/a/44934830/5647260 in regards to TJ's comment. Commented Aug 19, 2018 at 16:08

5 Answers 5

4

There are a couple of things going on here. The main one is that you're shadowing b, so the b outside the function isn't used within it. Instead, within it, you're creating a new array (because you've used a rest parameter, ...b) and assigning it to the b parameter. Since you call f with just one parameter, that array is empty. 1+[] is "1" because when either of the operands to + isn't a primitive (arrays aren't primitives), it's coerced to a primitive, and coercing an array to a primitive (indirectly) results in doing a .join(",") on the array. With a blank array, .join(",") is "". Then, since one of the operands is a string, the other operand (1) is coerced to string ("1") and it does "1"+"" which is, of course, "1". (Details on that last bit in the spec.)

answered Aug 19, 2018 at 16:04
Sign up to request clarification or add additional context in comments.

1 Comment

@Li357 - Fixed it, thanks for flagging that up. It's because ToPrimitive is used without any hint, and the default for arrays is number, but ToPrimitive on an array with hint number tries valueOf and then toString. Array's valueOf returns the array, which isn't primitive, so toString is used instead: tc39.github.io/ecma262/#sec-toprimitive
0

f(1) is the same as 1 + []

f(1,2,3) is the same as 1 + [2, 3]

That's all...

The first line const b = [1,2,3]; is not used because the b in the lambda expression is the argument, not the constant declared before.

answered Aug 19, 2018 at 16:04

1 Comment

oh yes! and the arguments are local scope in the function.
0

You can reference variables in a function call, however, when you define a function expression, the parameters name do not refer to any variables.

You'll get the expected result if you call the function like this:

alert(f(1, b));
answered Aug 19, 2018 at 16:04

1 Comment

"You'll get the expected result if you call the function like this:" Well, I don't think the OP has ever answered the question of what he/she expects. But note that if you just change the call as you suggest, b within f will be [[1, 2, 3]] (note that's an array inside an array), and the result would be "11,2,3" which I doubt very much is what the OP is expecting.
0

It takes the rest parameters ... as an array b.

While this is empty, it is converted to an empty string and both operands are treated as string, because if one is a string, then it adds all values as string.

The result is '1'.

const b = [1, 2, 3];
const f = (a, ...b) => a + '';
console.log(typeof f(1));

answered Aug 19, 2018 at 16:04

Comments

0

Reproducing this in my browser's development tools console looks like this:

> b = [1,2,3]
> f = (a, ...b) => a+b
> f(1)
< "1"
// so it results in the string 1, why's that?
// lets try logging what a and b are in the function
> g = (a, ...b) => console.log("a=%o, b=%o", a, b)
> g(1)
< a=1, b=[]
// ah, so b is an array, which is what the spread operator does 
// (gathers all remaining arguments into an array, so the question 
// is then what does JavaScript return for the number 1 added to an empty array?
> 1 + []
< "1"

This behavior is one of the many quirks of JavaScript when using the + operator on different types.

answered Aug 19, 2018 at 16:08

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.