如何在 ES2015 中编写命名箭头函数? [英] How do I write a named arrow function in ES2015?

查看:21
本文介绍了如何在 ES2015 中编写命名箭头函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,我正在尝试将其转换为 ES6 中的新箭头语法.它是一个命名函数:

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

有没有办法在没有 var 语句的情况下给它一个名字:

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

显然,我只能在定义后才能使用该函数.类似于以下内容:

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

ES6 中有没有新的方法可以做到这一点?

解决方案

如何在 ES2015 中编写命名箭头函数?

您按照您在问题中排除的方式进行操作:您将其放在赋值或属性初始值设定项的右侧,其中变量或属性名称可以合理地用作 JavaScript 引擎的名称.没有其他方法可以做到这一点,但这样做是正确的,并且完全包含在规范中.

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

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

这在 赋值运算符 >运行时语义:评估,它调用 抽象的 SetFunctionName 操作(该调用当前在步骤 1.e.iii).

类似地,运行时语义:PropertyDefinitionEvaluation 调用 SetFunctionName 并因此给这个函数一个真实的名字:

let o = {sayHello: 姓名 =>{console.log(`${name} 说你好`);}};

现代引擎已经为这样的语句设置了函数的内部名称;Edge 仍然可以在运行时标志后面的函数实例上将其作为 name 使用.

例如,在 Chrome 或 Firefox 中,打开 Web 控制台,然后运行以下代码段:

"use strict";让 foo = () =>{抛出新的错误();};console.log("foo.name 是:" + foo.name);尝试 {富();}赶上(e){控制台日志(e.stack);}

在 Chrome 51 及更高版本和 Firefox 53 及更高版本(以及带有实验标志的 Edge 13 及更高版本)上,当您运行它时,您会看到:

<前>foo.name 是: foo错误在 foo (http://stacksnippets.net/js:14:23)在 http://stacksnippets.net/js:17:3

注意 foo.name 是:fooError...at foo.

在 Chrome 50 及更早版本、Firefox 52 及更早版本以及没有实验性标志的 Edge 上,您会看到这一点,因为它们还没有 Function#name 属性(尚):

<前>foo.name 是:错误在 foo (http://stacksnippets.net/js:14:23)在 http://stacksnippets.net/js:17:3

请注意,foo.name is: 中缺少名称,但它 显示在堆栈跟踪中.只是在函数上实际实现 name property 的优先级低于其他一些 ES2015 特性;Chrome 和 Firefox 现在拥有它;Edge 有它在旗子后面,想必它不会在旗子后面太久了.

<块引用>

显然,我只能在定义后才能使用这个函数

正确.箭头函数没有函数声明语法,只有函数表达式语法,并且没有与旧式命名函数表达式(varf = 函数 foo() { };).所以没有等价于:

console.log(function fact(n) {如果 (n <0) {throw new Error("未为负数定义");}返回 n == 0 ?1 : n * 事实(n - 1);}(5));//120

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

const fact = n =>{如果 (n <0) {throw new Error("未为负数定义.");}返回 n == 0 ?1 : n * 事实(n - 1);};console.log(fact(5));

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

console.log((() => {const 事实 = n =>{如果 (n <0) {throw new Error("未为负数定义.");}返回 n == 0 ?1 : n * 事实(n - 1);};返回事实(5);})());//120

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

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.

这篇关于如何在 ES2015 中编写命名箭头函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆