Function declaration or function expression
R

1

6

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.

Rugose answered 25/12, 2012 at 3:34 Comment(3)
"redeclare the function every time it's declared so that you can do something like this" – they are re-referenced, only the declaration occurs once and it's hoisted. Haven't you confirmed in the previous paragraph, that you understand the hoisting?Usa
Yes I do understand hoisting in JavaScript. No, my sentence is perfectly clear. What I'm trying to say is that every time the interpreter encounters a FunctionDeclaration (every time it's declared) it should only hoist it upto the previous declaration of the function in the same scope (redeclare the function). Since this feature doesn't exist in JavaScript you can't invalidate it by citing current JavaScript standards. It's simply a suggestion. A suggestion to implement multiple declarations of the same function in JavaScript. Hope that brings you some clarity. Merry Christmas @UsaRugose
Oh, I see. Thanks Lord it didn't occur to anyone on the ES board. Merry Christmas, Aadit! :)Usa
B
5

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.

Boccie answered 25/12, 2012 at 3:41 Comment(6)
So you shouldn't declare functions inside block scopes. Perhaps that's a good programming practice.Rugose
beside javascript is async lang. so you need to define your function before you can call itSycee
@Janim007, the whole point of this question is that in JavaScript you can call a function topologically before it's defined.Usa
@Janim007 - JavaScript is not an asynchronous language. In fact there's no JavaScript construct which adds asynchronicity to the language. The event loop and setTimeout are not features of the language. They are features of the DOM, and are required for interactive programming in web pages: https://mcmap.net/q/537720/-settimeout-if-not-defined-in-ecmascript-spec-where-can-i-learn-how-it-works/783743Rugose
JavaScript is rather ... loosely ... designed, and the "hoisting" behavior isn't actually anywhere in the language spec as such. Functions defined in block scope are, quite simply, undefined behavior. They need to be at either global scope or in the top level of a function, or you're in undefined implementation-will-do-whatever-it-wants land. It could work. It could give a "undefined" exception. It could format your hard drive, subscribe your mother to the sweet potato of the month club, or tie-dye your cat. It's undefined. At least it's not C's level of undefined behavior.Boccie
I had a hard time believing that changing the syntax in which I defined my closure could cause Firefox to fail to load a source file dependency (!) and Require.js in dev mode not even checking that dependencies sent back are undefined (!) but that is exactly what happened. Now I know to always declare closures as variables...Twink

© 2022 - 2024 — McMap. All rights reserved.