0

Consider the following code:

if (window.addEventListener) {
   window.addEventListener('load', someFunction, false);
} else if (window.attachEvent) {
   window.attachEvent('onload', someFunction);
}

function someFunction() {
   alert('Execute!');
}

This works in Chrome, FireFox, IE. I get the alert "execute!". However, if I wrap this in a try-catch block like this:

try{
    if (window.addEventListener) {
       window.addEventListener('load', someFunction, false);
    } else if (window.attachEvent) {
       window.attachEvent('onload', someFunction);
    }

    function someFunction() {
       alert('Execute!');
    }
}catch(e){
    alert(e.message);
}

Then in FireFox I get "someFunction is not defined". I get "execute" in the other browsers.

Can someone explain why this is so? I've spent a day scouring the Internet for any resource that could remotely explain this.

Let's assume I don't have any control of the code inside the try block but I want to trap any potential errors so that code that falls below still gets executed. I was thinking the try-catch block would be the solution but since it doesn't work in this scenario with FireFox, is there an alternative?

codealfa
  • 91
  • 1
  • 9
  • Actually because `try-catch` is a block in javascript. You should take a look at `block scope` in javascript. – sadrzadehsina Dec 20 '14 at 14:38
  • 1
    pay attention to warnings: `Function declarations should not be placed in blocks. Use a function expression or move the statement to the top of the outer function.` – sadrzadehsina Dec 20 '14 at 14:38
  • Well I did say I didn't have control over the code inside the try block so I couldn't do that. The question really is why it works in other browsers but not FF – codealfa Dec 20 '14 at 14:43
  • And I do understand block scope but that doesn't explain why it would work without the try-catch – codealfa Dec 20 '14 at 14:46

2 Answers2

2

Here, these is a similar problem, I've made a summary:

  1. You can easily put the function "someFunction" declaration out the try-catch block.

  2. Wrapping the contents of the try block in an immediate function seems to restore that behavior:

    try {
      (function(){
        hello();
        function hello() { 
          alert("Hello world");
        }
      })
    } 
    catch (err) {
      alert(err);
    }
    
  3. Firefox interprets function statements differently and apparently they broke declaration hoisting for the function declaration, so Firefox work differently from other browsers.

Community
  • 1
  • 1
xdola
  • 562
  • 2
  • 8
  • 23
  • Ah yes, 2. is the workaround I was looking for. Guess I was wording my search ineffectively why I didn't come across that. – codealfa Dec 20 '14 at 15:02
  • I couldn't use this solution after all in my application. I realized I needed to access the variables declared inside the try block outside of the block. I guess there's no workaround for me. – codealfa Dec 21 '14 at 00:29
  • After all, point 1 should work – xdola Dec 21 '14 at 14:32
1

You can find more details about the ECMA spec here. As a general rule, functions within a block scope should always be defined at the top. I've never ran into this problem before because I've always followed that rule (perhaps from being burned in the early days).

This issue you're facing is because of the way firefox implements function hoisting in block scopes. You will face this problem not only in try-catch, but any block scope in Firefox.

Example of the issue in another block scope:

if(somevar==1) {
    somefunction(); // Will fail in Firefox

    function someFunction() {
       alert('Execute!');
    }
} 

Workarounds:

1. Move function declarations to the beginning of the block

try {
    function someFunction() {
       alert('Execute!');
    }

    somefunction(); // Works in all browsers
}
catch(e) {
    alert(e);
}

2. Wrap the entire block in an Immediately Invoked Function Expression (IIFE)

try {
    (function() { 
       function someFunction() {
           alert('Execute!');
       }

       somefunction(); // Works in all browsers
    })();
}
catch(e) {
    alert(a);
}

Example fiddle: http://jsfiddle.net/zz5mj7c2/6/

Community
  • 1
  • 1
Nick
  • 4,002
  • 4
  • 30
  • 41
  • In my specific application where I encounter this scenario I don't have control of the code inside the try block but variables inside the try block may need to be accessible outside that block so this wouldn't work for me. Thanks for the reply though..very helpful and informative. – codealfa Dec 21 '14 at 00:34