In the online REPL of Babel JS (http://babeljs.io/repl/), when I type in :
let a = (x) => x+1
It will be transpiled to:
"use strict";
var a = function a(x) {
return x + 1;
};
Here the var a = function a(x)
looks a bit confusing to me, because either var a = function(x)
or function a(x)
is enough as I understand.
Does anyone have ideas about when and why it is necessary to assign a named function to a variable?
Named Functions: In JavaScript, named functions are simply a way of referring to a function that employs the function keyword followed by a name that can be used as a callback to that function. Normal functions with a name or identifier are known as named functions.
Functions stored in variables do not need function names. They are always invoked (called) using the variable name.
When you assign a function object to another variable JavaScript does not create a new copy of the function. Instead it makes the new variable reference the same function object as original. It is just that two variables having different names are accessing the same underlying function object.
Programmers can create a single variable using the var, let, or const keywords and assign the function expression to that. However, creating a variable with the const keyword is recommended to assign the function as the function expression always remains constant.
There are really two different questions here:
let a = (x) => x + 1
get transpiled this way?In order to answer (2) we need to understand (1)-- which has been extensively discussed on SO and elsewhere.
Let's go through the three alternatives you mentioned:
Function declaration:
function a(x) { ... }
Syntactically, these must always begin with function
(reference). They are hoisted at parse time and create a named function in the local scope.
(Anonymous) Function expression:
var a = function (x) { ... }
var a
itself will be hoisted at parse time, but it will be undefined
until this line is executed at runtime.
Named Function expression:
var a = function a(x) { ... }
Though the syntax makes it looks like an assignment to a function declaration, this is actually just a function expression with a name. I find this confusing, but that's the syntax.
The big difference is between function declarations and function expressions. With a declaration, you can do:
a(1);
function a(x) { return x + 1; }
though attempting this with a function expression (named or anonymous) will cause an error.
- Why does let a = (x) => x + 1 get transpiled this way?
We're assigning the arrow function (x) => x + 1
to a block-scoped variable with let
, so we should expect that a
is not defined until after this line has been executed at runtime. This should be a function expression, not a function declaration.
Last, why is let a = (x) => x + 1
transpiled to a named function expression rather than a anonymous function expression? What's the difference? As Alnitak and others have pointed out:
So named function expressions have some nice properties that anonymous function expressions don't. But there actually seems to be disagreement on what should happen here. According to MDN:
Arrow functions are always anonymous
whereas this answer to Why use named function expressions? says:
"[As of ES6] a lot of "anonymous" function expressions create functions with names, and this was predated by various modern JavaScript engines being quite smart about inferring names from context... This is strewn throughout the spec"
Other references:
var functionName = function() {}
vs function functionName() {}
I've found that the best way to get a handle on this is playing around with the Babel REPL.
If you write:
function a(x) { }
then the function is hoisted to the top of the enclosing scope, and a
becomes available immediately at parse time within the entire scope.
However, when you write:
var a = function a(x) { }
then var a
will not have a defined value in the enclosing scope until this line is actually executed.
However, within that function, a different a
will exist as a locally scoped reference to the function itself.
By using the let a = function ...
construct Babel is being more consistent with the latter form, ensuring that a
is assigned at run time to a (named) function expression instead of using a parse time function declaration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With