2

Any reason why the following snippet shows different output in Firefox and Chrome:

var sayHo;
console.log(typeof(sayHey));
console.log(typeof(sayHo));
if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };
    sayHo = function() {
        console.log("Ho, inside if");
    };
}
else {
    function sayHey() {
       console.log("Hey, inside else");
    };
    sayHo = function() {
       console.log("Ho, inside else");
    };
}
sayHey();
sayHo();

Chrome(v31) outputs

  1. function
  2. undefined
  3. Hey, inside else
  4. Ho, inside if

Firefox(v26) outputs

  1. undefined
  2. undefined
  3. Hey, inside if
  4. Ho, inside if

I expected the same output what Chrome gave. During parse time, the function declaration inside will override the function declaration inside if. Because JavaScript will try to hoist both the function declarations, hence the override.

3
  • 1
    Function "statements" (formally named declarations) are not valid inside if statements. More info is available here: kangax.github.io/nfe/#function-statements Commented Dec 29, 2013 at 13:51
  • 1
    How does different browser yield different outputs ? Commented Dec 29, 2013 at 13:52
  • 1
    @DevendraLattu Since function declarations nested inside if statements is non-standard, browsers can implement it anyhow they like, hence the differences. Commented Dec 29, 2013 at 13:54

2 Answers 2

2

Firefox and Chrome use different JavaScript engines (SpiderMonkey and V8 respectively). The Chrome behaviour can be considered either a 'bug' or an 'ease of use feature'. In V8 function definitions inside if statements (rather than assignment of an anonymous function to a variable) are performed pre-execution. It's a design decision.

Sign up to request clarification or add additional context in comments.

4 Comments

Any reason why you consider the behavior of Firefox an error?
Function declarations are evaluated pre-execution in all engines. The reason why Firefox doesn't evaluate the func declaration here is because it is nested within an if-statement which is not valid in JavaScript. The proper response would be to throw a syntax error, however that would "break the web", so Firefox decided to delay evaluation instead. Chrome on the other hand decided to treat it as an non-nested func declaration.
Yeah, I should edit the answer to be clear about that rather than just assuming it's obvious from the context of the question.
Thanks aychedee and Sime Vidas for the explanation.
0

It all boils down to hoisting differences :

Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:

function foo() {
    bar();
    var x = 1;
}

is actually interpreted like this:

function foo() {
    var x;
    bar();
    x = 1;
}

Consider this example :

function test() {
    foo(); // TypeError "foo is not a function"
    bar(); // "this will run!"
    var foo = function () { // function expression assigned to local variable 'foo'
        alert("this won't run!");
    }
    function bar() { // function declaration, given the name 'bar'
        alert("this will run!");
    }
}
test();

this code is equivalent to :

  function test() {

        function bar() { // function declaration, given the name 'bar'
            alert("this will run!");
         }
        foo(); // TypeError "foo is not a function"
        bar(); // "this will run!"
        var foo = function () { // function expression assigned to local variable 'foo'
            alert("this won't run!");
        }

    }
    test();

Look what happened to the function declaration : it is hoisted.

Leet's look at simplier sample : http://jsbin.com/UKICENE/4/edit

console.log(typeof(sayHey));

if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };}

sayHey();

This will yield function in chrome.

But it will yield undefined in FF.

Hoeever - deferring the calculationm via setTimeout will yield the same result as chrome :

console.log(typeof(sayHey));//undefined

setTimeout(function (){console.log(typeof(sayHey));},1000); //function

if(true) {
    function sayHey() {
        console.log("Hey, inside if");
    };}

sayHey();

So , like Šime said , it delay the evaluation.

If you ask me , I think chrome is doing the right thing

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.