6

I am reading something on Variable Hoisting that I am not able understand exactly how to learn around it. I read W3C schools for the explanation. But, based on the sample code, I could not make what is hoisting.

code 1 [This is the code from w3c school]

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

    <script>
    var x = 5; // Initialize x
    var y;     // Declare y

    elem = document.getElementById("demo"); // Find an element 
    elem.innerHTML = x + " " + y;           // Display x and y

    y = 7;     // Assign 7 to y

    </script>
       </body>
    </html>

But the above code still displays 'undefined' for the variable y.

If I change the code as follows then it works fine. But, this below code is usual and not the different one to understand 'hoisting'

<script>
var x = 5;  // Initialize x
var y;
y = 7;
elem = document.getElementById("demo"); // Find an element 
elem.innerHTML = x + " " + y;           // Display x and y
</script>

Any help on this to understand 'Variable hoisting'?

3
  • y = 7; would not be hoisted in this setup because it is already declared with var y; at the top of the function. Commented Jun 1, 2015 at 13:47
  • 2
    I wouldn't trust the W3Schools explanation, MDN has a good example Commented Jun 1, 2015 at 13:48
  • 1
    this is a comprehensive explanation of variable and function Hoisting. adripofjavascript.com/blog/drips/variable-and-function-hoisting Commented Sep 8, 2016 at 13:30

4 Answers 4

7

(Note: I've added a brief discussion of ES2015's let and const at the end of this answer.)

Fundamentally, what variable hoisting means is that no matter where you see var in any given scope, it's as though it were at the very beginning of the scope. So these are all identical:

function foo() {
    var a = 42;
}

function foo() {
    var a;
    a = 42;
}

function foo() {
    a = 42;
    var a;
}

function foo() {
    var a;
    a = 42;
    var a;
}

They're processed by the JavaScript engine as though they were:

function foo() {
    var a;
    a = 42;
}

Here's an example actually using variable hoisting, and also giving an example of what I call The Horror of Implicit Globals (that's a post on my anemic little blog):

function foo() {
    a = 42;
    b = 67;

    console.log(a); // 42
    console.log(b); // 67

    var a;
}
foo();
console.log(typeof a); // undefined
console.log(typeof b); // number?!
console.log(b);        // 67?!

Why does b exist outside of foo? Because inside foo, these two lines do very different things:

a = 42;
b = 67;

The first line sets the local variable a, because we declared it. Yes, we declared it later, but we declared it.

The second line creates an implicit global variable b, because we never declared b anywhere in foo.

More (on my blog):


ES2015 (aka "ES6") introduced let and const. They're handled slightly differently from var:

  1. They have block scope rather than function or global scope.
  2. The declaration is hoisted to the top of the block, but they don't get any default value at that point; they get initialized (with undefined or the value you provide) only when the declaration is reached in the step-by-step execution of the code.

Demonstrating point #1 (block scope):

function foo() {
    {
        let a = 1;
        console.log(a); // 1
    }
    console.log(a); // ReferenceError: a is not defined
}
foo();

Demonstrating point #2: This would work with var, it doesn't work with let:

function foo() {
    a = 42; // ReferenceError: a is not defined
    let a;
}
foo();

The time between when the identifier is reserved (declaration) and when you can use it (initialization) is called the Temporal Dead Zone within which you can't use the variable.

Sign up to request clarification or add additional context in comments.

6 Comments

I’d like to add that variables appear to only be hoisted in function scope. An x = 2; at the top of the entire script actually creates a global variable bound to the window object (window.x is defined). In function scope however window.x would not be defined if x = 2; is on top and var x; comes later.
@Xufox: var hoisting is exactly the same at global scope as at function scope. Even at global scope, if there's a var x; anywhere, an x = ... before it will assign to that variable. That variable is also a global, but it's not the same kind of global as you'd get if there were no var x (but still an x = ... somewhere). Bizarre but true; you can delete non-var globals with delete; you can't delete var globals at all.
But there’s no difference between <script>x = 3; console.log(window.x) /* 3 */; var x;</script> and <script>x = 3; console.log(window.x) /* 3 */;</script> whereas there is a difference between <script>(function(){x = 3; console.log(window.x) /* undefined */; var x;})();</script> and <script>(function(){x = 3;console.log(window.x) /* 3 */;})();</script>.
@Xufox: Yes, there is. It has nothing to do with whether var hoisting is special in global scope, though (it isn't). It has to do with the fact that assigning to unbound symbols within a function in loose mode creates an implicit global.
@Xufox: There's another difference: What happens if you try to use them before assigning to them. With x, you'd get the value undefined. With y, you'd get a ReferenceError: jsfiddle.net/f9gsypL8/4
|
3

Javascript Engine will execute code in two phases

  1. Pre processing phase(or instantiation phase).
  2. Execution Phase.

Pre processing phase(or instantiation phase)- In Preprocessing phase, the script is scanned completely for all the declarations. var - is the identifier to declare a variable. So when var identifier is encountered, variable will be declared in the global scope. The value of the variable is - undefined

Execution Phase- In Execution Phase, the script is executed line by line. All the initializations will be done in this phase.

Example-1

For Below code snippet, In Pre processing phase, Javascript engine will scan through the code line by line, when it encounters line "var a", it will declare variable a in the global scope.

In the Execution phase, at line "a=10", variable 'a' will be initialized with value 10. when it encounters console statements, value 10 will be printed.

a=10;
console.log(a); // 10
var a;
console.log(a); // 10

This is how variable hoisting works.

1 Comment

nicely explained !
1

In Javascript, var x = 21; is broken into 2 parts: var x; and x = 21;.

The var x; part is always hoisted to the beginning of the enclosing function. The x = 21; part is left in its original place.

The same thing happens with function () {} declarations - this would be hoisted to the top of the enclosing function scope:

function pie () {
    return 21;
}

just like the var.

Comments

0

A variable can be used before it is declared

JavaScript Initializations are Not Hoisted

enter image description here

Function Hoisting As previously mentioned, function declarations are also hoisted. However, functions that are assigned to variables are not hoisted.

See below example

Function Declaration Overrides Variable Declaration When Hoisted enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.