I have a function that I am trying to convert to the new arrow syntax in ES6. It is a named function:
function sayHello(name) {
console.log(name + ' says hello');
}
Is there a way to give it a name without a var statement:
var sayHello = (name) => {
console.log(name + ' says hello');
}
Obviously, I can only use this function after I have defined it. Something like following:
sayHello = (name) => {
console.log(name + ' says hello');
}
Is there a new way to do this in ES6?
How do I write a named arrow function in ES2015?
You do it the way you ruled out in your question: You put it on the right-hand side of an assignment or property initializer where the variable or property name can reasonably be used as a name by the JavaScript engine. There's no other way to do it, but doing that is correct and fully covered by the specification.
Per spec, this function has a true name, sayHello
:
var sayHello = name => {
console.log(name + ' says hello');
};
This is defined in Assignment Operators > Runtime Semantics: Evaluation where it calls the abstract SetFunctionName
operation (that call is currently in step 1.e.iii).
Similiarly, Runtime Semantics: PropertyDefinitionEvaluation calls SetFunctionName
and thus gives this function a true name:
let o = {
sayHello: name => {
console.log(`${name} says hello`);
}
};
Modern engines set the internal name of the function for statements like that already; Edge still has the bit making it available as name
on the function instance behind a runtime flag.
For example, in Chrome or Firefox, open the web console and then run this snippet:
"use strict";
let foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
foo();
} catch (e) {
console.log(e.stack);
}
On Chrome 51 and above and Firefox 53 and above (and Edge 13 and above with an experimental flag), when you run that, you'll see:
foo.name is: foo Error at foo (http://stacksnippets.net/js:14:23) at http://stacksnippets.net/js:17:3
Note the foo.name is: foo
and Error...at foo
.
On Chrome 50 and earlier, Firefox 52 and earlier, and Edge without the experimental flag, you'll see this instead because they don't have the Function#name
property (yet):
foo.name is: Error at foo (http://stacksnippets.net/js:14:23) at http://stacksnippets.net/js:17:3
Note that the name is missing from foo.name is:
, but it is shown in the stack trace. It's just that actually implementing the name
property on the function was lower priority than some other ES2015 features; Chrome and Firefox have it now; Edge has it behind a flag, presumably it won't be behind the flag a lot longer.
Obviously, I can only use this function after I have defined it
Correct. There is no function declaration syntax for arrow functions, only function expression syntax, and there's no arrow equivalent to the name in an old-style named function expression (var f = function foo() { };
). So there's no equivalent to:
console.log(function fact(n) {
if (n < 0) {
throw new Error("Not defined for negative numbers");
}
return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120
You have to break it into two expressions (I'd argue you should do that anyway):
const fact = n => {
if (n < 0) {
throw new Error("Not defined for negative numbers.");
}
return n == 0 ? 1 : n * fact(n - 1);
};
console.log(fact(5));
Of course, if you have to put this where a single expression is required, you can always...use an arrow function:
console.log((() => {
const fact = n => {
if (n < 0) {
throw new Error("Not defined for negative numbers.");
}
return n == 0 ? 1 : n * fact(n - 1);
};
return fact(5);
})()); // 120
I ain't sayin' that's pretty, but it works if you absolutely, positively need a single expression wrapper.