我如何写一个命名箭头函数在ES2015?

我有一个函数,我试图转换为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中是否有新的方法来做到这一点?

116887 次浏览

不。箭头语法是匿名函数的缩写形式。匿名函数是匿名的。

命名函数用function关键字定义。

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

给出的例子是:

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'},

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

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

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


sayHello.name //=== 'sayHello'

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

这是es6

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

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

我如何写一个命名箭头函数在ES2015?

您可以按照您在问题中排除的方式执行:将它放在赋值或属性初始化器的右边,在那里变量或属性名可以被JavaScript引擎合理地用作名称。没有其他的方法来做到这一点,但这样做是正确的,并完全覆盖了规范。(它也适用于传统的匿名function表达式。)

根据规范,这个函数有一个真实的名字,sayHello:

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

它目前定义在赋值运算符>运行时语义:评估中,在那里执行抽象NamedEvalution操作(目前是步骤1.c.i)。(你可以通过将鼠标悬浮在标题中的NamedEvalution上并单击“引用”来看到这适用于任何地方)(之前,在ES2019之前,赋值运算符>运行时语义:评估使用抽象的SetFunctionName操作,步骤1.e。iii,但在ES2019以后,这个规范抽象被NamedEvalution取代。)

类似地,PropertyDefinitionEvaluation使用namedevalue,因此给了这个函数一个真实的名字:

let o = {
sayHello: (name) => {
console.log(`${name} says hello`);
}
};

现代引擎已经为这样的语句设置了函数的内部名称。

请注意:为了进行名称推断,函数表达式必须被赋值给目标对象。例如,这并没有推断出名称:

const sayHello = (void 0, (name) => {
console.log(name + ' says hello');
});
console.log(sayHello.name); // ""

这是因为函数表达式并没有被直接赋值给const,而是赋值给另一个操作符的操作数(在这种情况下,是逗号操作符,但对于[比如说]true && (name) => { }也是一样的)。

例如,在Chrome、Edge(基于chromium的v79版本)或Firefox中,打开web控制台,然后运行以下代码段:

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

在Chrome 51及以上版本和Firefox 53及以上版本(以及“;Legacy"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 is: fooError...at foo

在Chrome 50及更早版本,Firefox 52及更早版本,以及没有experimental标志的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(function fact(n) {
if (n < 0) {
throw new Error("Not defined for negative numbers");
}
return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120

你必须把它分解成两个表达式(我认为无论如何你都应该这么做):

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));

当然,如果你把它放在需要一个表达式的地方,你总是可以…使用箭头函数:

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

我并不是说这很漂亮,但如果你绝对需要一个表达式包装器,它就可以工作。


旁注:如果不想让函数从赋值给它的标识符中获取它的名称,该怎么办?那,假设你想要example.name在这里是"example" ?

const example = () => {};
console.log(example.name); // "example"

您可以通过使用任何不使用namedepreciation的表达式来避免它。做这类事情最流行的方法可能是逗号操作符:

const example = (0, () => {});
//              ^^^−−−−−−−−−^
console.log(example.name); // ""

0可以是你想要的任何东西,它被求值然后被丢弃,所以0是一个流行的选择。通过逗号操作符传递函数将断开赋值和函数表达式之间的直接链接,防止namedepreciation为函数提供名称example。(这类似于逗号操作符的其他著名用法,如(0, object.example)()调用object.example 没有,使object在调用中成为this的值,或(0, eval)("code"),执行eval,但不在正常情况下的当前范围内。)

(感谢Sebastian Simon在评论中提出这一点。)

为了写一个命名的箭头函数,你可以参考下面的例子,在这个例子中,我有一个名为LoginClass的类,在这个类中我写了一个名为successAuth箭头命名函数 class LoginClass {

    constructor() {


}


successAuth = (dataArgs)=> { //named arow function


}


}

您可以跳过函数部分和箭头部分来创建函数。例子:

 class YourClassNameHere{


constructor(age) {
this.age = age;
}


foo() {
return "This is a function with name Foo";
}


bar() {
return "This is a function with name bar";
}


}


let myVar = new YourClassNameHere(50);
myVar.foo();

实际上,它看起来像命名箭头函数的一种方式(至少在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);
}

enter image description here