I remember when I was interviewing as an intern at Tencent, the interviewer asked me this question.
At first I only knew of two declaration methods: function declaration and function expression. I couldn’t explain the specific differences. I happened to see a book on this topic recently and wanted to summarize it.
In ECMAScript, there are two most commonly used methods to create function objects, namely using function expressions or using function declarations. In this regard, the ECMAScript specification makes it clear that the function declaration must always have an identifier (Identifier), which is what we call the function name, and the function expression can be omitted.
Function declaration:
1. Create a new Function object, FormalParameterList specifies the parameters, and FunctionBody specifies the function body. Uses the scope chain in the currently running environment as its scope.
2. Create an attribute named Identifier for the current variable object, with the value Result(1).
Function expression:
(Function expressions are divided into anonymous and named function expressions)
The parsing process of named function expressions is as follows:
1. Create a new Object
2. Add Result(1) to the top of the scope chain
3. Create a new Function object, specify the parameters in FormalParameterList, and specify the function body in FunctionBody. Uses the scope chain in the currently running execution environment as its scope.
4. Create an attribute named Identifier for Result(1), its value is Result(3), read-only, cannot be deleted
5. Remove Result(1)
from the scope chain
6. Return Result(3)
The official documentation is very difficult to read. Simply put, ECMAScript distinguishes the two through context: if function foo(){} is part of an assignment expression, it is considered a function expression. And if function foo(){} is contained within a function body, or is located in (the top level of) the program, it is parsed as a function declaration. Obviously, when the identifier is omitted, the "expression" can only be an expression.
There is another situation:
This case is also a function expression, which is a function enclosed in a pair of parentheses. In its context, () constitutes a grouping operator, and the grouping operator can only contain expressions. More Example:
Let’s briefly talk about the similarities and differences between function declarations and function expressions. There is a subtle yet important difference in the behavior of declarations and expressions.
First, function declarations are parsed and evaluated before any expressions are parsed and evaluated. Even if the declaration is the last line in the source code, it will be evaluated before the first expression in the same scope. It is easier to understand by looking at an example. In the following example, the function fn is declared after alert. However, when alert is executed, fn is already defined:
To summarize briefly, what is the difference?
1. Declarations are always parsed at the beginning of the scope;
2. Expressions are evaluated only when encountered.
Function declaration has another important feature, that is, the behavior of controlling function declaration through conditional statements is not standardized, so different results may be obtained in different environments. That is:
So, what are the actual rules for using function declarations?
FunctionDeclaration can only appear in Program or FunctionBody. Syntactically, they cannot appear inside a Block ({ ... }), for example, within an if, while, or for statement. Because Block can only contain Statement, but not SourceElement such as FunctionDeclaration.
On the other hand, if you take a closer look at the generation rules, you will find that the only way for an Expression to appear in a Block is to make it part of an ExpressionStatement. However, the specification clearly states that ExpressionStatement cannot start with the keyword function. What this actually means is that FunctionExpression cannot appear in Statement or Block (don't forget that Block is composed of Statement).
Due to the above restrictions, whenever a function appears in a block (like in the example above), it should actually be treated as a syntax error rather than a function declaration or expression.
So when should we use function declarations or function expressions? Function declarations can only appear in "program code", which means they can only appear in other function bodies or in the global space; their definitions cannot be assigned to a variable or attribute, or passed as a parameter in a function call; the following An example is the allowed usage of function declarations. foo(), bar() and local() are all declared through the function declaration mode:
When you cannot syntactically use a function declaration, you can use a function expression. For example: pass a function as a parameter or define a function in an object literal:
My knowledge is limited, please correct me if there are any mistakes.