In-depth explanation of the Hoisting mechanism in JavaScript

Source: Internet
Author: User
This article mainly introduces the Hoisting mechanism in JavaScript, which involves issues related to variable declaration in JS. For more information, see Hoisting Mechanism

The javascript variable Declaration has the hoisting mechanism. During execution, the JavaScript engine will promote all variable declarations to the beginning of the current scope.

First read a piece of code

var v = "hello";(function(){ console.log(v); var v = "world";})();

What is the result of this code?
The answer is: undefined.
This Code illustrates two problems,
First, the variable v in the function scope overrides the variable v in the upper scope. Less code changes

var v = "hello";if(true){ console.log(v); var v = "world";}  

The output is "hello", indicating that javascript has no block-level scope. A function is the only structure in JavaScript that has its own scope.

Second, in the function scope, the variable v Declaration is promoted. So the initial code is equivalent:

var v = "hello";(function(){ var v; //declaration hoisting console.log(v); v = "world";})();  

Declaration, definition, and initialization

The Declaration declares that a name exists, and the definition assigns a bucket to the name, while the initialization assigns an initial value to the bucket allocated by the name.
Use C ++ to express these three concepts

Extern int I; // This is a declaration, indicating that name I already exists somewhere
Int I; // This is the declaration and definition name I, allocating storage space for I
I = 0; // This is the initialization name I, and the initial value is 0.
In javascript, this is the case.

Var v; // declare the variable v
V = "hello"; // (define and) initialize the variable v
Because javascript is a dynamic language, its variables do not have a fixed type, and its storage space size changes with initialization and assignment, therefore, the variable definition is not the same as the traditional static language.

Declaration escalation

All declarations in the current scope are promoted to the beginning of the scope, including declarations of variables and functions.

(function(){ var a = "1"; var f = function(){}; var b = "2"; var c = "3";})();  


The declaration of variables a, f, B, and c will be promoted to the very beginning of the function scope, similar to the following:

(function(){ var a,f,b,c; a = "1"; f = function(){}; b = "2"; c = "3";})();

Note that the function expression is not upgraded, which is also the difference between the function expression and the function declaration. Further look at the differences between the two:

(Function () {// var f1, function f2 () {}; // hoisting, declared f1 (); // ReferenceError: f1 is not defined f2 (); var f1 = function () {}; function f2 (){}})();

In the code above, the function declaration f2 is promoted, so it is okay to call f2 before. Although the variable f1 is also upgraded, the value of f1 after being upgraded is undefined, and its real initial value is assigned to the function expression during execution. Therefore, only declarations are promoted.

Name Resolution Sequence

In javascript, a name enters the scope in four ways. The priority order is as follows:
1. Language built-in: All scopes have the this and arguments keywords.
2. Formal parameters: function parameters are valid in the function scope.
3. function declaration: function foo (){}
4. Variable Declaration: such as var bar;

The priority of the name declaration is shown above. That is to say, if the name of a variable is the same as that of a function, the name of the function overwrites the name of the variable, regardless of the order in the code. However, the name Initialization is performed in the order it is written in the Code and is not affected by the above priority. Check the Code:

(function(){  var foo;  console.log(typeof foo); //function  function foo(){}  foo = "foo";  console.log(typeof foo); //string})();  

If a formal parameter contains multiple variables with the same name, the last parameter with the same name will overwrite other parameters with the same name, even if the last parameter with the same name is not defined.

The above name resolution priority has exceptions. For example, the built-in name arguments can be overwritten.

Name function expression

You can specify a name for a function expression like a function declaration, but this does not make the function expression a function declaration. The name of the namefunction expression does not enter the namespace or be promoted.

F (); // TypeError: f is not a function
Foo (); // ReferenceError: foo is not defined
Var f = function foo () {console. log (typeof foo );};
F (); // function
Foo (); // ReferenceError: foo is not defined
The name of the name function expression is valid only within the scope of the function.

Let's take a look at the following example:

var myval = "my global var";(function() { console.log(myval); // log "my global var"})();

The above Code clearly outputs "my global var", but if we modify the above Code as follows:

var myval = "my global var";(function() { console.log(myval); // log "undefined" var myval = "my local var";})();

The execution result is an undefined output. The reason for this result is that the variable declaration is promoted. The above code is equivalent to the following:

var myval = "my global var";(function() { var myval; console.log(myval); // log "undefined" myval = "my local var";})();

Only the declaration part of the variable is promoted and Initialization is not performed immediately. Therefore, undefined is output.

However, this mechanism is not only manifested in common variables, but also in functions. For example, the following code cannot be correctly executed:

(function() { fun(); // Uncaught TypeError: undefined is not a function var fun = function() { console.log("Hello!"); }})();

Because it is equivalent:

(function() { var fun; fun(); // Uncaught TypeError: undefined is not a function fun = function() { console.log("Hello!"); }})();

An error occurs because the function declaration is also promoted and not initialized immediately.

Of course, this method of defining a function is called a "function expression" and there will be an improvement mechanism. If it is the following "function declaration" method, there will be no improvement mechanism problems at all:

(function() { fun(); function fun() { console.log("Hello!"); // log "Hello!" }})();

This is also the main difference between function declaration and function expression.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.