Search code examples
javascripthoisting

No hoisting in catch statement?


I have this code:

(function() {
   var ex;
   try {
       throw new Error('blah');
   } catch(ex) {
       console.log('ex i here:', ex);
   }
   console.log('ex out here:', ex);

   return 'hi';
})()

This logs:

ex i here: Error('blah');

ex out here: undefined

Why is this so? I would think due to hoisting, ex would get set outside of this block scope, so it should be available in ex out here.

I expected it to work similar to a for loop:

for (i=0; i<2; i++) {
}
console.log(i); // gives 2

Solution

  • You are messing few things up.

    Variables that are defined as var have function-scope. The parameter in catch is not hoisted, it has block-scope (only in that catch part).

    As you can see in this example: The ab is hoisted and then is accessible outside the catch part. The ex2 does not exist outside the context.

    (function() {
       var ex;
       try {
           throw new Error('blah');
       } catch(ex2) {
           var ab = 3;
           console.log('ex is here:', ex2.message);
       }
       console.log(ab);
       console.log(ex2);
       console.log('ex out here:', ex);
    
       return 'hi';
    })()

    In your example, there is different variable created with the same name, but different scope. If this happens, then (in almost all languages) the "deepest" variable in your context is used. If you want to take the error outside of catch with hositing, you can:

    (function() {
       try {
           throw new Error('blah');
       } catch(ex2) {
           var ex = ex2;
           console.log('ex is here:', ex2.message);           
       }
       console.log(ex.message);
    
       return 'hi';
    })()