How do I write a named arrow function in ES2015?

前端 未结 8 815
余生分开走
余生分开走 2020-11-22 16:29

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         


        
8条回答
  •  北海茫月
    2020-11-22 17:03

    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.

提交回复
热议问题