search

Home  >  Q&A  >  body text

ES 2017: async function vs AsyncFunction object vs async function expression

I just read about async functions and found some similar features for ES2017. It's causing a lot of confusion and I just want to ask:

    What is the difference between
  1. async function, AsyncFunction (used to create an async function), and an async function expression (which I think is just another async function)?
  2. When should one format be used instead of another?

Highlights of everyone's quirks and performances would be greatly appreciated!

P粉459440991P粉459440991276 days ago429

reply all(1)I'll reply

  • P粉287726308

    P粉2877263082024-03-26 00:44:29

    There are four ways to create functions in Javascript. There are also four ways to create asynchronous functions in Javascript, which are exact mirrors of each other.

    To demonstrate how this works, I used a simple sleep function, declared globally:

    function sleep(time) {
        return new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve();
            }, time);
        });
    }

    Function declaration

    function speak() { return 'Hi'; }
    async function speak() { await sleep(1000); return 'Hi'; }

    This is the simplest way to declare a function. It can be declared once and hoisted to the top of the current function scope.

    Function declarations are exactly the same as async function declarations, except that async functions always return a Promise and allow you to use await.

    Function expression

    let speak = function() { return 'Hi'; } // anonymous function expression
    let speak = function speakFn() { return 'Hi'; } // named function expression
    
    let speak = async function() { await sleep(1000); return 'Hi'; } // anonymous asynchronous function expression
    let speak = async function speakFn() { await sleep(1000); return 'Hi'; } // named asynchronous function expression

    Function expressions look very much like function declarations. However, they are not promoted to the top of the function scope. You can redefine them as many times as needed. They can be defined inline. They can be anonymous or named: if they are named, the name refers to a function within that function's scope.

    Function expressions are exactly the same as async function expressions, except that async functions always return a Promise and allow you to use await.

    Arrow function

    let speak = word => 'Hi ' + word; // one parameter
    let speak = (word1, word2) => 'Hi ' + word1 + word2; // multiple parameters
    
    let speak = async word => { await sleep(1000); return 'Hi ' + word; } // one parameter
    let speak = async (word1, word2) => { await sleep(1000); return 'Hi ' + word1 + word2; } // multiple parameters

    Arrow functions are a quick and short way to define a function, introduced in ES2015 (ES6). They are equivalent in most respects to function expressions, except that they are always anonymous, and the value of this is always lexically bound, i.e. inherited from the outer scope.

    Arrow functions are exactly the same as async arrow functions, except that async functions always return a Promise and allow you to use await. (They are slightly different in the above statements because there are multiple statements inside each async function. This means that these statements need to be contained in a block {} and return Need to be explicit. This is also true for ordinary arrow functions longer than one statement.)

    Function constructor

    let speak = new Function('word', 'return "Hi " + word;');
    let speak = new AsyncFunction('word', 'await sleep(1000); return "Hi " + word;')

    The function constructor allows you to dynamically define functions using strings. Note that they always run in the global scope and have no access to the scope in which they are defined. They are only useful in rare circumstances. Personally I don't think an async function constructor would be useful. The author of ES2017 agrees with me, since AsyncFunction is not a global object and must be obtained first using const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor.

    Functions created using the function constructor are exactly the same as functions created using the anonymous function constructor, except that the async function always returns a Promise and allows you to use await. (But you already guessed it, right?)

    reply
    0
  • Cancelreply