我有一个函数,我试图转换为ES6中的新箭头语法。它是一个命名函数:

function sayHello(name) {
    console.log(name + ' says hello');
}

有没有办法给它一个没有var语句的名字:

var sayHello = (name) => {
    console.log(name + ' says hello');
}

显然,我只能在定义这个函数之后才能使用它。大致如下:

sayHello = (name) => {
        console.log(name + ' says hello');
    }

在ES6中有新的方法来做到这一点吗?


当前回答

实际上,它看起来像命名箭头函数的一种方式(至少在chrome 77…)是这样做的:

"use strict";
let fn_names = {};
fn_names.foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

其他回答

这是es6

是的,我认为你想要的是这样的:

const foo = (depth) => {console.log("hi i'm Adele")}
foo -> // the function itself
foo() -> // "hi i'm Adele"

如果你所说的“named”是指你想要设置箭头函数的.name属性,那么你很幸运。

如果在赋值表达式的右边定义了一个箭头函数,引擎将接受左边的名称并使用它来设置箭头函数的.name。

var sayHello = (name) => {
    console.log(name + ' says hello');
}

sayHello.name //=== 'sayHello'

话虽如此,你的问题似乎更多的是“我能得到一个箭头函数来提升吗?”这个问题的答案恐怕是一个大大的“不”。

似乎这在ES7中是可能的: https://babeljs.io/blog/2015/06/07/react-on-es6-plus#arrow-functions

给出的例子是:

class PostInfo extends React.Component {
  handleOptionsButtonClick = (e) => {
    this.setState({showOptionsModal: true});
  }
}

ES6的箭头函数体与围绕它们的代码共享相同的词法this,这得到了我们想要的结果,因为ES7属性初始化器的作用域是这样的。

请注意,为了让它与babel一起工作,我需要启用最具实验性的ES7 stage 0语法。在我的webpack.config.js文件中,我更新了babel加载器,如下所示:

{test: /\.js$/, exclude: /node_modules/, loader: 'babel?stage=0'},

实际上,它看起来像命名箭头函数的一种方式(至少在chrome 77…)是这样做的:

"use strict";
let fn_names = {};
fn_names.foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

我如何写一个命名箭头函数在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.)

(感谢塞巴斯蒂安·西蒙在评论中提出这一点。)