Someone Please explain what is going on here.
var y = 1;
if (function f(){return 'some text';}) {
y += typeof f;
}
console.log(y);// "1undefined"
if i change it into function expression
var y = 1;
if (a = function f(){return 'some text';}) {
y += typeof a;
}
console.log(y);// "1function"
4 Answers 4
The condition of an if statement is always an expression. In the second case its an assignemnt expression that sets the global (!) variable a to a function, in the first case its just a function expression, and the function goes into nowhere (it is not stored anywhere). f is just the name of the function inside of the function itself (for recursion). Therefore f is not defined outside of it.
Comments
A function declaration creates a variable with the same name in the current scope.
function a() {
function b() {
}
}
In the above example, a variable b is created in the scope of a.
A function expression creates a variable with the same name in its own scope.
function a() {
(function b() {
})
}
In the above example, a variable b is created in the scope of b but not a.
In your first example (a named function expression), f doesn't exist outside the function so it is undefined.
In your second example (also a named function express), you are explicitly assigning the function to a (an implicit global) so it is defined.
Neither of your examples features a function declaration, despite your question title. Putting the function keyword inside an if () condition makes it an expression just as much as putting it on the RHS of an =.
Comments
The difference is that the first example exhibits a function expression as the if statement's conditional expression. Function expressions do not produce a named entity in the enclosing scope, per ECMA-262 [2015] §14.1.20 (bold emphasis mine):
NOTE 2
The BindingIdentifier in a FunctionExpression can be referenced from inside the FunctionExpression's FunctionBody to allow the function to call itself recursively. However; unlike in a FunctionDeclaration, the BindingIdentifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
The reason it is interpreted as a FunctionExpression rather than a FunctionDeclaration is because it is given as the conditional expression of an if statement, as defined in ECMA-262 [2015] §13.6.7:
Runtime Semantics: Evaluation
IfStatement : if ( Expression ) Statement else Statement
Your second example works because the if conditional expression is an assignment expression, the evaluation of which assigns the result of the function expression (i.e., a function object) to the variable a which has already been declared in the enclosing scope.
The references given here are to ECMAScript 2015, but nearly identical provisions are given in earlier versions of the specification.
Comments
Look at this examples:
// function declaration
function A() { return 'AAAA'; }
console.log('A: ', typeof A); // A: function
// mixing function declaration and expression - wrong way
b = function B() { return 'BBBB'; };
console.log('b: ', typeof b); // b: function
console.log('B: ', typeof B); // B: undefined
// Why?
// 'B' is declared inside an expression and 'dies' after the expression
// ends, i.e. after b get assigned the right side of '='
// 'b', on the other side, got the function assigned and lives
// further on the scope.
// function declaration - right way
b2 = function() { return 'BBBB'; };
console.log('b2: ', typeof b2); // b2: function
// declaring the function inside the 'if' expression... same as with B
if(function C() { return 'C';}) {
console.log('C (in): ', typeof C); // undefined
}
console.log('C: (out)', typeof C); // undefined
// ... it's the same as in here:
x = (function D() { return 'D';});
console.log('x: ', typeof x); // function
console.log('D: ', typeof D); // undefined
// assigning a variable (same as with 'B' example)
if(z = function Z() { return 'Z'; }) {
console.log('z: ', typeof z); // function
console.log('Z: ', typeof Z); // undefined
}
// ... and the same as with Z
y = (z2 = function Z2() { return 'Z2'; });
console.log('y: ', typeof y); // function
console.log('z2: ', typeof z2); // function
console.log('Z2: ', typeof Z2); // undefined
typeof fin the first snippet until I remembered it wasn't actually a function declaration.