Function Declarations Within Blocks according to the Google JavaScript style guide
Asked Answered
C

1

6

According to the Google JavaScript style guide, function declarations should not be declared within blocks since this is not a part of ECMAScript. However, I'm not entirely clear on what counts as a block.

Specifically, I have a constructor function and I want to define a function within the scope of that constructor. Would this count as a function within a block, since it is within a set of {}? If so, does that mean every function declaration must be global?

Some code for good measure:

WRONG (?)

function Constructor() {
    function Shout () { alert('THE BEST UX IS IN ALL CAPS.'); }
}

RIGHT (?)

function Constructor() {
    var Shout = function () { alert('THE BEST UX IS IN ALL CAPS.'); };
}
Crenation answered 1/7, 2013 at 17:9 Comment(2)
A function is not a block.Abandoned
kangax.github.io/nfe/#function-declarations-in-blocksOrtegal
A
25

A function is not a block. A block is (for example) what follows a while, for, or if.

First, understand that function declarations (function foo() {}) are hoisted to the top of the scope of their containing function (i.e., you can access a declared functions by name anywhere in the same scope as the declaration).:

foo();
function foo() { }

This out-of-order code is 100% legal because the declaration of foo is hoisted to above the foo() invocation. However, now imagine you have a conditional declaration:

if(false) {
    function foo() { }
}

From a language-design perspective, should foo be hoisted? The program flow will never enter the block, but we customarily hoist all declarations. Due to this confusion, declarations inside blocks are not part of the grammar defined by the ECMAScript spec (though each implementation does support this grammar, but causes a different, nonstandard effect in each).

Having a function inside another function does not carry this confusion:

function bar() {
    function foo() { }
}

It's obvious that foo will be hoisted to the top of bar (whenever it runs).

Thus, your first example is perfectly fine.

Abandoned answered 1/7, 2013 at 17:16 Comment(9)
Thought so. So what defines a block? A Google search indicates {}'s are blocks. This implies the obvious blocks if, else, for, while, try, catch. But function is ambiguous.Crenation
@MatthewJamesDavis Functions always have the function keyword, followed by a sometimes optional identifier, followed by parentheses with an optional parameter list inside, followed by the braces with the function body inside. So it's not ambiguous. An empty block is ambiguous with an empty object literal though.Hornswoggle
@MatthewJamesDavis bfavaretto said it pretty clearly, but I'll try to reiterate: curly braces indicate a block except when they are part of an object literal or a function definition/expression. I know that seems like a bit of a tautology, but it's what the spec says. I just did a search and I agree with you that's it's hard to find a clear reference on the subject; regardless, now you know the truth of the matter!Abandoned
@Abandoned + 1 "A function is not a block" - applies to any function, for example, is a function expression also not a considered a block?Androecium
@Daniel nope, not a block! Largely, the differences between func expressions and declarations are limited to hoisting and variable names (i.e., a named function expression bar like foo(function bar(){ ... }) doesn't declare a variable named bar). The scope behavior inside both types should be identical, and neither is a block.Abandoned
thanks, @Abandoned +1, last question, a function expression if I can put it inside a block but a function declaration can't, right? thanks in advanceAndroecium
@Daniel Exactly right (or maybe "shouldn't" instead of "can't"). To change my example above, there's no problem with if(false) { do_blah(function foo() { }); } because you would never expect this expression to create a variable named foo in any case (unlike the declaration, which normally would).Abandoned
The named function expression in this example looks like a function declaration, I guess they differ in that a named function expression is passed as a callback or assigned to something and the function declaration is just at the top-level of a scope, thanks +1Androecium
@Daniel Exactly right, a func expression can look exactly like a declaration but it's used within a larger statement, like an assignment. A function declaration is technically a special kind of function expression that (1) always has a name (expressions can have names or not) and (2) is its own complete statement (i.e., can be the entire content between two semicolons)Abandoned

© 2022 - 2024 — McMap. All rights reserved.