I was just hacking away on a side project when I wrote this code:
const screencastMock = {
findOne: () => { }
};
My intention was to make findOne
return an empty object literal ({}
) but it actually returns undefined
.
Can you spot my mistake?
When JavaScript sees () => { }
, it interperts the { }
part as a block statement instead of an empty object literal:
const screencastMock = {
findOne: () => { var insideABlockStatement = true; var owned = true; } // valid JavaScript!
};
The block statement doesn't contain a return statement so this
is implicitly returned. In this context, this
was undefined
, hence why findOne
returns undefined
.
To successfully return an empty object literal, I should have surrounded the empty object literal in parentheses, like this:
const screencastMock = {
findOne: () => ({})
}
I found this error amusing because I'm well aware of this caveat with arrow functions and yet it still tripped me up 😆! If I wasn't aware of this caveat, who knows how long I could have been stuck here...
I wounder if there's an ESLint plugin available to help avoid this mistake...?
I will answer my own question:
I guess it's because arrow functions expect either an expression or a block.
A fat arrow only knows about block, it doesn't know about object literal. So if you use { } it always treats as a block.
http://exploringjs.com/es6/ch_arrow-functions.html#_arrow-function-syntax
The specs call it "ConciseBody", it's either an expression or function body:
http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions
One thing I don't understand in the spec is what
AssignmentExpression
is.Why is it called assignment expression? Since we can do this:
const f = x => x;
in this case the body of the arrow function is just
x
, it's not an assignment expression.