So suppose I have something like this
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
This outputs "1undefined". I thought it should have output "1function", because function f(){} should have been hoisted above the if. This is clearly not the case - why? I thought function declarations and bodies were always hoisted to the top of the scope?
So suppose I have something like this
var x = 1;
if (function f(){}) {
x += typeof f;
}
x;
This outputs "1undefined". I thought it should have output "1function", because function f(){} should have been hoisted above the if. This is clearly not the case - why? I thought function declarations and bodies were always hoisted to the top of the scope?
Share Improve this question asked Jul 27, 2015 at 21:57 praks5432praks5432 7,79232 gold badges93 silver badges158 bronze badges 3- Actually, it is, see: developer.mozilla/en-US/docs/Web/JavaScript/Reference/… – heartyporridge Commented Jul 27, 2015 at 22:05
- 1 I think this is a named function expression, not a function declaration. The scope of the name is just the body of the function being defined, not the surrounding function. – Barmar Commented Jul 27, 2015 at 22:21
-
It's like
var foo = function f() {};
. – Barmar Commented Jul 27, 2015 at 22:21
3 Answers
Reset to default 8Function declarations are hoisted. Function expressions are not.
This creates a named function expression:
if(function f(){})
It doesn't do anything except check to see if the function expression is truthy. (Function expressions are always truthy.)
Regarding named function expressions, see https://kangax.github.io/nfe/#named-expr:
An important detail to remember is that this name is only available in the scope of a newly-defined function
This code is outside the scope of the new function expression, and therefore f
is undefined:
x += typeof f;
Within a named function expression, you can refer to its name without a problem:
(function f() {
alert(typeof f); //function
})();
alert(typeof f); //undefined
As far as I know ES5 does not define the behavior for function declarations inside blocks.
Quoting Kangax:
FunctionDeclarations are only allowed to appear in Program or FunctionBody. Syntactically, they can not appear in Block ({ ... }) — such as that of if, while or for statements. This is because Blocks can only contain Statements, not SourceElements, which FunctionDeclaration is. If we look at production rules carefully, we can see that the only way Expression is allowed directly within Block is when it is part of ExpressionStatement. However, ExpressionStatement is explicitly defined to not begin with "function" keyword, and this is exactly why FunctionDeclaration cannot appear directly within a Statement or Block (note that Block is merely a list of Statements).
Because of these restrictions, whenever function appears directly in a block (such as in the previous example) it should actually be considered a syntax error, not function declaration or expression. The problem is that almost none of the implementations I've seen parse these functions strictly per rules (exceptions are BESEN and DMDScript). They interpret them in proprietary ways instead.
Function declarations are statements. The conditional part of an if-statement is an expression, so what you have is a function expression; it cannot be a function declaration. And so it isn't hoisted, since only function declarations are.