'var hoisting Question in javascript and it's output

I'm just wondering why is it that the output for the 3rd console.log is 2? I know that var statements are hoisted (without their value initialization) to the top of the global or function scope it belongs to, even when it’s inside a with or catch block. I'm still currently studying javascript at the moment and no one can explain to me properly, since I was expecting that the value of the last 2 console.log is undefined. Why is it that the 2nd console.log is undefined and the last console.log output is 2? Why the last one is able to access the value of y inside the catch block?

(function () {
    try {
        throw new Error();
    } catch (x) {
        var x = 1, y = 2;
        console.log(x);
    }
    console.log(x);
    console.log(y);
})();


Solution 1:[1]

Both x,y are hoisted. var is function scoped so they will be hoisted without initialization at top of the block.

  (function () {
        var x,y;
        try {
            throw new Error();
        } catch (x) {
            x = 1;
            y = 2;
            console.log(x);
        }
        console.log(x);
        console.log(y);
    })();

You have a local variable in the catch block due to catch(x). When you do x=1 inside the catch block, you are only changing the value of your local x (the one which is the parameter to the catch block). The inner x shadows the outer x. The outside x is still undefined. Updating y will update the outer one, hence your output.

Solution 2:[2]

The explaination has everything to do with variable hoisting and assignment.

In the catch block, variable y is hoisted to the function-level of the annonymous function

Since your catch block is written as "catch (x)" the var statement is assigning its local value of x within the catch block to 1. That is why the first console.log(x) returns 1.

The way your code is written, variable x is undefined on the function-level resulting in the second console.log(x) returning undefined.

variable y is being hoisted to the function level (despite the assignment appearing in the var line withing the catch block. So the var assignment in the catch block is storing the value of y as 2 at the function-level.

That is why it is appearing as 2 in your third console.log statement.

Please see the following code examples with the introduction of a z variable within the try/catch blocks

Example #1:

(function () {
    try {
        var z='before';
        throw new Error();
        var z='after';
    } catch (x) {
        var x = 1, y = 2
        console.log(x);
    }
    console.log(x);
    console.log(y);
    console.log(z);
})();

where console.log(z) will respond with 'before'

Example #2:

(function () {
    try {
        var z='before';
        throw new Error();
        z='after';
    } catch (x) {
        var x = 1, y = 2, z='catch'
        console.log(x);
    }
    console.log(x);
    console.log(y);
    console.log(z);
})();

where console.log(z) will respond with 'catch'

Solution 3:[3]

In JS var has a function scope so you can access y anywhere in the function. For x you have two separate variables one in catch(x) and the second is initialized in the inside catch.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tushar Shahi
Solution 2
Solution 3 Mateen