3

What's the deal with javascript function hoisting inside of if statements? Does js just not do it? The following code, when run in a browser works just fine. It will alert "hey" after two seconds.

<script>
setTimeout(hey,2000)
function hey(){
    alert('hey')
}
</script>

But add a trival if statement around this:

<script>
if(true){
setTimeout(hey,2000)

function hey(){
    alert('hey')
}
}
</script>

and suddenly it complains that hey is not defined.
Now if you change the callback from hey to function(){hey()}, like this:

<script>
if(true){
setTimeout(function(){hey()},2000)

function hey(){
    alert('hey')
}
}
</script>

then it starts working again, even with the if statement. So what's going on?

J-bob
  • 8,380
  • 11
  • 52
  • 85
  • 4
    I [can't reproduce](http://jsfiddle.net/7omodL3z/) the problem you describe. – Quentin Dec 03 '14 at 20:56
  • 1
    http://jsfiddle.net/r1oc1joh/ JFiddle accepts it. – jackncoke Dec 03 '14 at 20:58
  • I'm using firefox. You can just cut and paste that code directly into a file without any other code and it happened to me. – J-bob Dec 03 '14 at 20:58
  • Both worked here ... http://jsfiddle.net/rfornal/3807s37n/1/. Just tried it in Firefox with no issues. – rfornal Dec 03 '14 at 20:58
  • 1
    Worked for me as well. I think you must have run some different code than what you pasted here to cause that error :) – thataustin Dec 03 '14 at 20:59
  • Don't put function declarations in `if` statements anyway. – Pointy Dec 03 '14 at 20:59
  • Exact duplicate, but I already used my close-vote on "cannot reproduce" before I realized this was a FF-specific problem: http://stackoverflow.com/questions/4069100/why-cant-i-use-a-javascript-function-before-its-definition-inside-a-try-block – user229044 Dec 03 '14 at 21:11
  • @rfornal You totally broke the examples by running them together. You can't do that, or the second `hey`, outside the `if (true) { }` is the one that gets hosted. If you're faithfully copied the code and tried it in Firefox, you'd have found the problem. – user229044 Dec 03 '14 at 21:13
  • You're right ... only in Firefox ... strange. – rfornal Dec 03 '14 at 21:15
  • don't declare functions inside conditionals. Just asking for compiler problems – charlietfl Dec 04 '14 at 01:43

2 Answers2

4

Firefox doesn’t hoist function declarations in blocks, apparently. The behavior you're seeing is specific to Firefox, and documented nearly identically elsewhere.

To paraphrase:

Works:

if ( hasRequiredJQueryVersion ) {
   // Test data here
   // Library code here
}

Works everywhere except Firefox:

if ( true ) {
    testFunction();
    function testFunction() {
        alert(‘testFunction called’);
    }
}

This is behavior you should avoid, as it is specific to Firefox, even though Firefox's behavior may technically be correct.

user229044
  • 232,980
  • 40
  • 330
  • 338
  • oh good, I was beginning to think I was crazy with everyone else saying they could't reproduce the problem. Interestingly, the jsFiddles that people provided still worked on Firefox. Why would it work in jsFiddle but not work otherwise? – J-bob Dec 03 '14 at 21:11
  • @J-bob The JSFiddles *don't* work for me in Firefox. None of them do, except the one by rfornal which (I've commented above) is actually broken because they incorrectly reproduced the problem. – user229044 Dec 03 '14 at 21:13
  • ah yes, I (stupidly) didn't realize that rfornal's jsfiddle wouldn't expose the problem because of how they pasted both exapmles together. – J-bob Dec 03 '14 at 21:18
-2

The third example is consistent w/ the second: setTimeout isn't actually calling hey, so doesn't care that it hasn't been defined. It is only when the timeout occurs that hey is called, by which point is has been defined.

Scott Hunter
  • 48,888
  • 12
  • 60
  • 101
  • You don't have to call it; `setTimeout` is actually distracting from the real issue which is that Firefox's behavior is broken (or at least, different from every other browser). It isn't hoisting the function. – user229044 Dec 03 '14 at 21:07
  • OP gave an example where, even though the function wasn't hoisted (as evidenced in the second example), the call worked in the third. I was only trying to explain that seeming contradiction. Knock it for not being a complete answer, but it was addressing part of the question (which pointing out the "real issue" does not address). – Scott Hunter Dec 03 '14 at 21:20