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
}
In strict mode of ES5, function declarations cannot be nested inside of an if block as shown in the question.
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”.
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.
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.
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:
- Let funcEnv be the result of calling NewDeclarativeEnvironment passing the running execution context’s Lexical Environment as the argument
- Let envRec be funcEnv’s environment record.
- Call the CreateImmutableBinding(N) concrete method of envRec passing the String value of Identifier as the argument.
- 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.- Call the InitializeImmutableBinding(N, V) concrete method of envRec passing the String value of Identifier and closure as the arguments.
- Return closure.
So, when you create a function in an expression,
a new environment context will be created (see first item)
the function's name will be bound to the newly created environment (see the third item).
The function body will be used to create the actual function object (see the fourth item)
The actual function object created is bound to the function's name in the newly created context (see the fifth item)
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With