我如何写一个命名箭头函数在ES2015?
您可以按照您在问题中排除的方式执行:将它放在赋值或属性初始化器的右边,在那里变量或属性名可以被JavaScript引擎合理地用作名称。没有其他方法可以做到这一点,但这样做是正确的,并且在规范中完全涵盖了这一点。(它也适用于传统的匿名函数表达式。)
根据规范,这个函数有一个真实的名字sayHello:
const sayHello = (name) => {
Console.log (name + ' say hello');
};
console.log (sayHello.name);/ /“sayHello”
This is currently defined in Assignment Operators > Runtime Semantics: Evaluation where it does the abstract NamedEvalution operation (currently step 1.c.i). (You can see everywhere this applies by hovering your mouse over NamedEvalution in the header there and clicking "References".) (Previously, before ES2019, Assignment Operators > Runtime Semantics: Evaluation used the abstract SetFunctionName operation, step 1.e.iii, but in ES2019 onward this specification abstraction was replaced with NamedEvalution.)
类似地,PropertyDefinitionEvaluation使用NamedEvalution,从而给这个函数一个真实的名字:
let o = {
sayHello: (name) => {
console.log(`${name} says hello`);
}
};
现代引擎已经为这样的语句设置了函数的内部名称。
注意:要进行名称推断,必须将函数表达式直接赋值给目标。例如,这并没有推断出名称:
const sayHello = (void 0, (name) => {
Console.log (name + ' say hello');
});
console.log (sayHello.name);/ / "
这是因为函数表达式没有被直接赋值给const,它是一个操作数,赋值给另一个操作符(在这种情况下,是逗号操作符,但对于[say] true && (name) =>{}也是一样的)。
例如,在Chrome、Edge(基于chromium的v79版本)或Firefox中,打开web控制台,然后运行以下代码段:
“使用严格的”;
let foo =() =>{抛出新的错误();};
Console.log ("foo.name is: " + foo.name);
尝试{
foo ();
} catch (e) {
console.log (e.stack);
}
在Chrome 51及以上版本和Firefox 53及以上版本(以及带有实验标志的“Legacy”Edge 13及以上版本,或“Chromium”Edge 79以上版本)上运行时,你会看到:
foo.name is: foo
Error
at foo (http://stacksnippets.net/js:14:23)
at http://stacksnippets.net/js:17:3
注意foo.name是:foo和Error…在foo。
在Chrome 50和更早的版本,Firefox 52和更早的版本,以及没有实验标志的Legacy Edge上,你会看到这个,因为它们没有Function#name属性(还):
foo.name is:
Error
at foo (http://stacksnippets.net/js:14:23)
at http://stacksnippets.net/js:17:3
注意,foo.name is:中缺少名称,但它显示在堆栈跟踪中。只是在函数上实际实现name属性的优先级低于其他ES2015特性;Chrome和Firefox现在都有;Edge把它放在旗子后面,应该不会在旗子后面太久了。
显然,我只能在定义这个函数之后才能使用它
正确的。箭头函数没有函数声明语法,只有函数表达式语法,并且在老式的命名函数表达式(var f = function foo(){};)中没有与名称等效的箭头。所以没有等价物:
Console.log(函数事实(n) {
如果(n < 0) {
抛出新的错误(“没有为负数定义”);
}
返回n == 0 ?1: n * fact(n - 1);
} (5));/ / 120
你必须把它分解成两个表达式(我认为你应该这样做):
Const fact = n => {
如果(n < 0) {
抛出新的错误("没有为负数定义");
}
返回n == 0 ?1: n * fact(n - 1);
};
console.log(事实(5));
当然,如果你必须把它放在需要一个表达式的地方,你总是可以……使用箭头函数:
Console.log (() => {
Const fact = n => {
如果(n < 0) {
抛出新的错误("没有为负数定义");
}
返回n == 0 ?1: n * fact(n - 1);
};
返回的事实(5);
}) ());/ / 120
我并不是说这很漂亮,但如果你绝对需要一个表达式包装器,它就可以工作。
旁注:如果不想让函数从赋值给它的标识符中获取它的名称,该怎么办?假设您不希望example.name在这里是“示例”?
Const示例= ()=> {};
console.log (example.name);/ /“例子”
您可以通过使用任何不使用namedepreciation的表达式来避免它。做这类事情最流行的方法可能是逗号操作符:
Const示例= (0,()=> {});
// ^^^ −−−−−−−−−^
console.log (example.name);/ / "
The 0 there can be anything you want, it's evaluated and then thrown away so 0 is a popular choice. Passing the function through the comma operator breaks the direct link between the assignment and the function expression, preventing NamedEvaluation from providing the name example for the function. (This is similar to other famous uses of the comma operator, like (0, object.example)() which calls object.example without making object the value of this within the call, or (0, eval)("code"), which does an eval, but not in the current scope as it normally would.)
(感谢塞巴斯蒂安·西蒙在评论中提出这一点。)