I remember when interviewing Tencent interns, the interviewer asked me this question.
//What are the differences between the following two declaration methods
function foo(){};
var bar = function foo(){};
At the beginning, I only knew that there were two ways of declaration, one was function declaration and the other was function expression, but I couldn't say it very well. I happened to see this book recently, so I 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 function declarations must always carry an identifier, which is what we call the function name, and function expressions can be omitted.
Function declaration:
function Identifier ( FormalParameterList opt){ FunctionBody }
The function declaration parsing process is as follows:
1. Create a new Function object, FormalParameterList specifies parameters, and FunctionBody specifies function body. Take the scope chain in the currently running environment as its scope.
2. Create a property named Identifier for the current variable object, with the value Result(1).
Function expression:
(Function expressions are divided into anonymous and named function expressions)
function Identifier opt(FormalParameterList opt){ FunctionBody } //Here is a named function expression
The parsing process of named function expressions is as follows:
1. Create a new Object object
2. Add Result(1) to the top of the scope chain
3. Create a new Function object, FormalParameterList specifies parameters, and FunctionBody specifies function body. Take the scope chain in the currently running execution environment as its scope.
4. Create a property named Identifier for Result(1), whose value is Result(3), read-only, and cannot be deleted.
5. Remove Result(1) from the scope chain
6. Return to Result(3)
The official document is very difficult to read. Simply put, ECMAScript distinguishes the two by context: if function foo(){} is part of an assignment expression, it is considered to be a function expression. And if function foo(){} is contained in a function body, or is located in the program (the uppermost layer), it is parsed as a function declaration. Obviously, when the identifier is omitted, "expression" can only be an expression.
function foo(){}; // declared because it is part of the program
var bar = function foo(){}; // Expression because it is part of the AssignmentExpression
new function bar(){}; // expression, because it is part of the New Expression (NewExpression)
(function(){
function bar(){}; // declared because it is part of the function body (FunctionBody)
})();
There is another situation:
(function foo(){})
This situation is also a function expression, which is contained in a pair of parentheses. In its context, () constitutes a grouping operator, and the grouping operator can only contain expressions. For more examples:
function foo(){}; // function declaration
(function foo(){}); // Function expression: note that it is included in the grouping operator
try {
(var x = 5); // The grouping operator can only contain expressions, not statements (var here is a statement)
}
catch(err) {
// SyntaxError (because "var x = 5" is a statement, not an expression - the value must be returned for evaluation of the expression, but the value may not be returned for evaluation of the statement. - Translation
}
The following briefly talks about the similarities and differences between function declarations and function expressions. There are very subtle and important differences in the behavior of statements and expressions.
first,Function declarations are parsed and evaluated before any expression is parsed and evaluated.. Even if the declaration is located on 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:
alert(fn()); //Output Helloworld!
function fn() {
return 'Helloworld!';
}
A brief summary, what is the difference?
1. Declarations are always parsed at the beginning of the scope;
2. Expressions are only calculated when they are encountered.
Function declaration has another important feature.That is, the behavior of controlling function declarations through conditional statements is not standardized, so different results may be obtained in different environments.. That is:
// Never do this!
// Different browsers will have different results.
if (true) {
function foo() {
return 'first';
}
}
else {
function foo() {
return 'second';
}
}
foo();
// Remember, in this case, use function expressions:
var foo;
if (true) {
foo = function() {
return 'first';
};
}
else {
foo = function() {
return 'second';
};
}
foo();
So, what are the actual rules for using function declarations?
FunctionDeclaration can only appear in Program or FunctionBody. Syntactically, they cannot appear in Block ({ ... }), for example, in if, while, or for statements. Because Block can only contain Statement, but cannot contain SourceElement such as FunctionDeclaration.
On the other hand, if you look closely at the rules of production, you will find that the only situation where Expression (expression) appears in a Block is to make it part of ExpressionStatement (expression statement). However, the specification clearly stipulates that ExpressionStatement cannot start with the keyword function. This actually means that FunctionExpression cannot also appear in Statement or Block (don't forget that Block is composed of Statement).
Due to the above limitations, as long as the function appears in the block (as in the example above), it should actually be considered 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 be in other function bodies or global space; their definitions cannot be assigned to a variable or attribute, or they may appear in function calls as a parameter; the following examples are allowed usage of function declarations, foo(), bar() and local() are all declared through function declaration patterns:
// Global environment
function foo() {}
function local() {
// Local environment
function bar() {}
return bar;
}
When you cannot use function declarations syntactically, you can use function expressions. For example: pass a function as a parameter or define a function in an object literal:
// This is an anonymous function expression
callMe(function () {
// Pass a function as a parameter
});
// This is a named function expression
callMe(function me() {
// Pass a function as a parameter, the function name is me
});
// Other function expressions
var myobject = {
say: function () {
// I am a function expression
}
};
Knowledge is limited, if there are any mistakes, please feel free to correct them.