Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the function defined in an 'if' condition's expression part not visible outside?

Tags:

javascript

if (function f() {}) {
    console.log(f) // Throw an error: f is not defined
}

Why will the log cause an error, the f isn't already defined in the above expression?


You'd expect this is equivalent to:

function f () {}
if (true) {
    console.log(f); // Throw an error: f is not defined
}
like image 445
hh54188 Avatar asked Mar 31 '14 14:03

hh54188


People also ask

Can I write a function inside if condition?

In strict mode of ES5, function declarations cannot be nested inside of an if block as shown in the question.

Why are functions called as part of an expression?

Functions are values. They can be assigned, copied or declared in any place of the code. If the function is declared as a separate statement in the main code flow, that's called a “Function Declaration”. If the function is created as a part of an expression, it's called a “Function Expression”.

Can we call function inside if condition in JavaScript?

Answer 55ee2c5d9113cbdba6000063You will have to call the quarter() function with an argument so that the return-Value with the remainder 3 will result in zero. Javascript has the so-called modulo-operator if used it will return the rest-value.

What is the difference between a function expression and a function declaration?

The main difference between a function expression and a function declaration is the function name, which can be omitted in function expressions to create anonymous functions. A function expression can be used as an IIFE (Immediately Invoked Function Expression) which runs as soon as it is defined.


2 Answers

When you say

function f () {}

It is a function declaration statement. This function will be defined in the enclosing environment. So, if it is defined inside another function, then the function will be defined within that environment, where you can access this function by name.

But, when you use the function declaration in an expression, it will not be treated as Function Declaration, but Function Expression and that will be evaluated like this (Quoting from ECMA Script 5.1 Standard Specification)

13 Function Definition: Semantics

The production

FunctionExpression :

 function Identifier ( FormalParameterListopt ) { FunctionBody }

is evaluated as follows:

  1. Let funcEnv be the result of calling NewDeclarativeEnvironment passing the running execution context’s Lexical Environment as the argument
  2. Let envRec be funcEnv’s environment record.
  3. Call the CreateImmutableBinding(N) concrete method of envRec passing the String value of Identifier as the argument.
  4. Let closure be the result of creating a new Function object as specified in 13.2 with parameters specified by FormalParameterListopt and body specified by FunctionBody. Pass in funcEnv as the Scope. Pass in true as the Strict flag if the FunctionExpression is contained in strict code or if its FunctionBody is strict code.
  5. Call the InitializeImmutableBinding(N, V) concrete method of envRec passing the String value of Identifier and closure as the arguments.
  6. Return closure.

So, when you create a function in an expression,

  1. a new environment context will be created (see first item)

  2. the function's name will be bound to the newly created environment (see the third item).

  3. The function body will be used to create the actual function object (see the fourth item)

  4. The actual function object created is bound to the function's name in the newly created context (see the fifth item)

  5. Then the function object is returned.

It is up to the program to assign the function object to variable in the current environment context to retain the function. Otherwise, when the expression evaluation is done, the newly created environment context becomes invalid. So, the function f will not be visible outside.

like image 77
thefourtheye Avatar answered Oct 14 '22 09:10

thefourtheye


Your assumption is incorrect. Those two snippets are not equivalent. The first is a named function expression where you don't store the value (the actual function object). Such an object is always truthy - and thus the if get's executed.

The function name for those functions is (or rather should be) only visible inside the function itself (except for some early IE versions). So, because f simply does not exist, a ReferenceError is thrown when you try to pass it to console.log.

like image 34
Yoshi Avatar answered Oct 14 '22 10:10

Yoshi