如何在ES2015中编写命名箭头功能?

jha*_*amm 192 javascript ecmascript-6 arrow-functions

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

function sayHello(name) {
    console.log(name + ' says hello');
}
Run Code Online (Sandbox Code Playgroud)

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

var sayHello = (name) => {
    console.log(name + ' says hello');
}
Run Code Online (Sandbox Code Playgroud)

显然,我只能在定义之后使用此功能.如下:

sayHello = (name) => {
        console.log(name + ' says hello');
    }
Run Code Online (Sandbox Code Playgroud)

ES6中有新的方法吗?

T.J*_*der 199

如何在ES2015中编写命名箭头功能?

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

根据规范,此函数具有真实名称,sayHello:

var sayHello = name => {
    console.log(name + ' says hello');
};
Run Code Online (Sandbox Code Playgroud)

这在Assignment Operators> Runtime Semantics:Evaluation中定义,它调用抽象SetFunctionName操作(该调用当前在步骤1.e.iii中).

类似地,Runtime Semantics:PropertyDefinitionEvaluation调用SetFunctionName,因此给这个函数一个真正的名字:

let o = {
    sayHello: name => {
        console.log(`${name} says hello`);
    }
};
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

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及更早版本以及没有实验标记的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
Run Code Online (Sandbox Code Playgroud)

你必须把它分成两个表达式(我认为你应该做的反正):

let 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));
Run Code Online (Sandbox Code Playgroud)

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

console.log((() => {
    let 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
Run Code Online (Sandbox Code Playgroud)

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

  • @trusktr:他们所做的一个例外可能适合你的目的,那么:如果你将一个函数赋给一个*existing*对象的属性,那么名字就不会被设置:`o.foo =()=> {};`不给功能一个名字.这[故意](/sf/answers/2933847171/)可防止信息泄露. (3认同)

Jör*_*tag 85

不.箭头语法是匿名函数的缩写.匿名函数是匿名的.

命名函数使用function关键字定义.

  • 对于问题**,这个答案的第一个字是正确的**因为OP排除了你命名箭头功能的方式.但答案的其余部分完全不正确.查看规范中使用[abstract`SetFunctionName`操作](http://www.ecma-international.org/ecma-262/6.0/index.html#sec-setfunctionname)的位置.`let a =()=> {};`根据规范和现代引擎定义一个名为**的**函数(名称为`a`)(在其中抛出错误以查看); 他们只是不支持`name`属性(但它在规范中,他们最终会到达那里). (16认同)
  • 正如@DenysSéguret所说,匿名函数_不是_shortform.你会得到一个_hard binded_函数.您可以在http://bit.do/es2015-arrow看到已编译的结果,以便更好地了解这意味着...... (15认同)
  • @DenysSéguret:你可以*简单地命名它们,它在规范中.你按照OP在问题中排除的方式来做,这给函数(不仅仅是变量)一个真实的名字. (4认同)
  • @TJCrowder感谢您提供的信息,以及您的[实用答案](http://stackoverflow.com/a/37488652/263525).我不知道这个(非常非常奇怪)的功能. (4认同)
  • 这个答案是不正确的.@TJCrowder在下面正确回答了这个问题 (4认同)

小智 44

如果通过'named',你的意思是你想要.name设置箭头函数的属性,那么你很幸运.

如果在赋值表达式的右侧定义了箭头函数,则引擎将采用左侧的名称并使用它来设置箭头函数.name,例如

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

sayHello.name //=== 'sayHello'
Run Code Online (Sandbox Code Playgroud)

话虽如此,你的问题似乎更多"我可以获得一个箭头功能来提升吗?".这个问题的答案是一个很大的"不",我很害怕.

  • 我错了:虽然name不是直接可变的,你可以这样配置它:Object.defineProperty(sayHello,'name',{value:'sayHello'}) (2认同)