7

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"
3
  • 5
    These are both expressions, and in a function expression, its name is only visible inside the function. Commented Nov 14, 2018 at 16:02
  • To be honest, I had to do a double-take when I saw the output of typeof f in the first snippet until I remembered it wasn't actually a function declaration. Commented Nov 14, 2018 at 16:19
  • You should have a look at kangax.github.io/nfe . Commented Nov 14, 2018 at 19:24

4 Answers 4

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.

Sign up to request clarification or add additional context in comments.

Comments

2

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

0

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

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.