Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable hoisting in javascript

Tags:

javascript

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'?

like image 696
User123 Avatar asked Dec 25 '22 18:12

User123


1 Answers

(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):

  • Poor, misunderstood var

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.

like image 140
T.J. Crowder Avatar answered Jan 10 '23 00:01

T.J. Crowder