A brief analysis of the difference between function declaration and function expression in JavaScript

  • 2020-05-19 04:14:29
  • OfStack

I remember the interviewer asked me this question when I was interviewing an intern at tencent.


// What are the differences between the two statements
 
function foo(){};
 
var bar = function foo(){}; 

We only know that there are two ways to declare a function and one way to declare a function, so what's the difference? Recently, I happened to see some books on this subject, so I want to summarize them.

In ECMAScript, there are two most common ways to create a function object, using either a function expression or a function declaration. In response, the ECMAScript specification makes clear that function declarations must always have an identifier (Identifier), which is what we call a function name, and that function expressions can be omitted.

Function declaration:


function Identifier ( FormalParameterList opt){ FunctionBody }

The parsing process of function declaration is as follows:

1. Create an new Function object, FormalParameterList specifies the parameters, FunctionBody specifies the function body. Take the chain of scopes in the current running environment as its scope.

2. Create a property named Identifier with the value Result(1) for the current variable object.

Function expression:

(function expressions are classified into anonymous and named function expressions)


  function Identifier opt( FormalParameterList opt){ FunctionBody }  // Here's a named function expression

The parsing process of named function expression is as follows:

1. Create an new Object object
2. Add Result(1) to the top of the scope chain
3. Create an new Function object, FormalParameterList specifies the parameters, FunctionBody specifies the function body. Take the chain of scopes in the currently running execution environment as its scope.
4. Create a property named Identifier for Result(1) with a value of Result(3), read only, and not deleted
5. Remove Result(1) from the scope chain
6. Return Result (3)

The official document reads like a mouthful. Simply put, ECMAScript distinguishes between the two by context: if function foo(){} is part 1 of an assignment expression, it is considered a functional expression. If function foo(){} is included in a function or in a program, it is parsed as a function declaration. Obviously, in the absence of identifiers, an "expression" can only be an expression.


function foo(){}; // Declaration, because it is procedural 1 Part of the
 
var bar = function foo(){}; // Expression, because it is an assignment expression ( AssignmentExpression ) 1 Part of the
 
new function bar(){}; // Expression, because it is New Expressions ( NewExpression ) 1 Part of the
 
(function(){
    function bar(){}; // Declaration, because it is the body of the function ( FunctionBody ) 1 Part of the
})();

There is one more case:


(function foo(){})

This case is also a function expression, which is included in the 1 pair of parentheses. In its context, () forms a grouping operator, and the grouping operator can only contain expressions. More examples:


function foo(){}; // Function declaration
 
(function foo(){}); // Function expression: notice that it is included in the grouping operator
 
try {
(var x = 5); // The grouping operator can contain only expressions, not statements (here) var Statement)
}
catch(err) {
// SyntaxError (because" var x = 5 "Is 1 Statement, not expression - expression evaluation must return a value, but statement evaluation does not necessarily return a value. Translation -
}

Here's a quick look at the similarities and differences between function declarations and function expressions. There is a subtle but important difference between the behavior of statements and expressions.

First, the function declaration is parsed and evaluated before any expression is parsed and evaluated. Even if the declaration is in the last line of source code, it is evaluated before the first expression in the same 1 scope. So let's do an example that's easier to understand. In the following example, the function fn is declared after alert. However, at the time alert is executed, fn is already defined:


alert(fn()); // The output Helloworld!  
 
function fn() {
return 'Helloworld!';
}


To summarize, what is the difference?

1. Declarations are always resolved at the beginning of a scope;
2. Expressions are not evaluated until they are met.

Another important feature of function declarations is that conditional statements that control the behavior of function declarations are not standardized, so different environments may produce different results. Is that:


// Don't do it!
// Different browsers will return different results,
 
if (true) {
function foo() {
return 'first';
}
}
else {
function foo() {
return 'second';
}
}
foo();
 
 
// Remember to use a function expression in this case:
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 (function declaration) can only appear in Program (program) or FunctionBody (function body). Syntactically, they cannot appear in Block (block) ({... }), such as cannot appear in if, while, or for statements. Because Block (block) can only contain Statement (statement), not SourceElement (source element) such as FunctionDeclaration (function declaration).

On the other hand, if you look closely at the 1 generation rule, you will find that only 1 can make Expression (expression) appear in Block (block), that is, as part 1 of ExpressionStatement (expression statement). However, the specification explicitly states that ExpressionStatement (expression statements) cannot begin with the keyword function. This means, in effect, that FunctionExpression (function expression) is also not present in Statement (statement) or Block (block) (remember that Block (block) is made of Statement (statement)).

Because of the above limitations, whenever a function appears in a 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 appear in other function bodies or in the global space. Their definition cannot be assigned to a variable or property, or passed as a parameter in a function call. The following example is the permitted use of function declaration, foo(), bar(), and local() are all declared by function declaration mode:


// The 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, passing a function as a parameter or defining a function in an object literal:



// This is a 1 An anonymous function expression
callMe(function () {
 
// pass 1 I'm taking five functions as arguments
});
 
// This is a 1 Two named function expressions
callMe(function me() {
 
// pass 1 The function is called me
});
 
// Other functional expressions
var myobject = {
    say: function () {
 
// I am a function expression
}
};

Limited knowledge, if there is a mistake, welcome to correct.


Related articles: