javascriptscopeecmascript-5function-expressionjavascript-function-declaration

Function declaration or function expression


I just ran into a problem when defining a function in a block scope. Consider the following program:

try {
    greet();

    function greet() {
        alert("Merry Christmas!");
    }
} catch (error) {
    alert(error);
}

I expected this program to alert Merry Christmas!. However in Firefox is gives me the following ReferenceError:

ReferenceError: greet is not defined

On Opera and Chrome it alerts the greeting as I expected it to.

Evidently Firefox treats the function inside the block scope as a FunctionExpression while Opera and Chrome treat it as a FunctionDeclaration.

My question is why does Firefox behave differently? Which implementation is more logical? Which one is standards compliant?

I understand that declarations in JavaScript are hoisted and so if the same function is declared in two or more different blocks in the same scope then there'll be a name conflict.

However wouldn't it be more logical to redeclare the function every time it's declared so that you can do something like this:

greet(); // Merry Christmas!

function greet() {
    alert("Merry Christmas!");
}

greet(); // Happy New Year!

function greet() {
    alert("Happy New Year!");
}

I think this would be very useful, in addition to solving the block scoping problem I described above.


Solution

  • Actually, function declarations inside block scopes is expressly not standardized and the behavior is implementation dependent. Different implementation respond differently. You'd get the same weirdness if you tried to declare a function inside an if statement.

    The ES5 spec recommends that implementers make function declarations inside blocks be marked as a warning or error.