1

Recently I noticed a behavior difference between Firefox and other browsers for the following javascript code:

var condition = true;
A();

function A() {

    var x=0;

    for(var i=0; i<10; i++) {
        if(condition) {
            ++x;
            B();
        }

        function B() {
                console.log("B function. x = "+x);
        }
    }
}

Chrome, Opera, IE output:

B function. x = 1
B function. x = 2 
B function. x = 3
B function. x = 4
B function. x = 5
B function. x = 6
B function. x = 7
B function. x = 8
B function. x = 9
B function. x = 10

Firefox output:

ReferenceError: B is not defined

However, there are no complaints from Firefox and gives out the same result as other browsers, if I put the definition of function B before the call, like this:

for(var i=0; i<10; i++) {

        function B() {
                console.log("B function. x = "+x);
        }

        if(condition) {
            ++x;
            B();
        }
    }

Based on this quote from Mozilla developer site:

Functions must be in scope when they are called, but the function declaration can be below the call

I understand the call, A() works. But I am not clear on why there is a difference in behavior between Firefox and others in calling B(), when the call is before definition.

While trying to narrow down the cause, I read about function hoisting here, which says Firefox doesnt do hoisting when inside an if block, but the definition was never inside the if statement in my case, so Im confused.

Razor
  • 40
  • 4
  • 2
    Placing a function declaration in a block (i.e., not in top-level code in a function or global code) is [not legal ECMAScript](http://kangax.github.io/nfe/#function-declarations-in-blocks), and browsers that allow it (i.e., all of them) are providing a custom extension of the language specification. You are observing two different custom extensions of the language. The statement "*Firefox doesnt do hoisting when inside an `if` block*" is a little misleading: Firefox doesn't do hoisting in *any* block, including `for`. – apsillers Sep 05 '13 at 16:24
  • @apsillers - So is it safe to assume this issue is **solely** because Firefox doesnt do hoisting inside any block? – Razor Sep 05 '13 at 17:25
  • From the code you have posted here, yes, lack of hoisting for function declarations in blocks would account for the observed behavior perfectly. – apsillers Sep 05 '13 at 17:27

1 Answers1

3

Firefox does not hoist function declarations outside of for blocks either. ECMA standard says it's okay. The documentation you linked to is not applicable only to if blocks, but for blocks as well.

Joe Frambach
  • 25,568
  • 9
  • 65
  • 95
  • 1
    You've got a couple of statements in reverse: you mean *in*-side, and the ECMAScript spec does *not* allow function declarations inside blocks. – bfavaretto Sep 05 '13 at 16:27
  • "Firefox does not hoist function declarations [to] outside of `for` blocks [from inside the block]. ECMA standard says it's okay [that this behavior happens]." I don't think I was wrong. I just wasn't clear. – Joe Frambach Sep 05 '13 at 17:28