<script type="text/javascript">
function func(){
}
var foo="foo";
</script>
<script type="text/javascript">
var foo="foo";
function func(){
}
</script>
At the beginning, when func is a function and foo is "undefined", but I want to know which is the first to be defined, func or foo?
Identifiers of both, variable and function declarations (and also formal parameters for function code) are made when entering the execution context, that's actually before the code execution.
In the case of variables, as you noted it, they are initialized with the undefined value at that stage, the assignment takes places after, when control reaches the assignment expression, e.g.:
var foo = "outer";
(function () {
alert(foo); // undefined
var foo = "inner";
})();
In the above code, we can see how the foo identifier holds the undefined value, that's because when entering the function execution context, the local foo variable was initialized.
That's one of the reasons why people recommend to declare your variables at the top of the function (to resemble what actually happens)
Functions declarations are also hoisted, you can actually use them before its declaration, because as we know, it was made before the code execution, for example:
func(); // "bar"
function func () {
return "bar";
}
See also:
Variable Instantiation Process
In
var foo = "foo";
function func() {
}
there are two things going on
Declaration
Initialization
foo and func are declared simoultaneously.
The initialization of func is hoisted to the top. So functions are initialized before vars.
So the order of operations is
foo and func declared
func initialized to a Function object
foo initialized to "foo"
This is clearest in the code
var foo = bar;
function bar() {}
where after this code runs, typeof foo === 'function'.
I believe identifiers become defined as their declarations are encountered.
Functions in javascript are always parsed and defined first.
<script type="text/javascript">
alert('before func: ' + func); // Print function as string
alert('before somevar: ' + somevar); // Print undefined
function func() {
}
var somevar = "hello";
alert('after func: ' + func); // Print function as string
alert('after somevar: ' + somevar); // Print hello
</script>
Related
The reason why in (A) "function" is printed out is probably because of hoisting respectively because in the creation stage the function is created in the variable object before the variable foo.
But if the function is created before the variable foo, how come I can't resolve the function (see (D)) but instead I can resolve the variable (see (C))?
(function() {
console.log(typeof foo); // (A) function pointer
var foo = 'hi';
function foo() {
return 'hello';
}
console.log(foo); // (C) hi
foo();// (D) TypeError: foo is not a function
})();
The is the order of events
var foo is hoisted and declares the variable foo.
function foo() {} is hoisted, redeclares the variable foo and assigns it a value (a function)
console.log(typeof foo) logs the function
foo = 'hi' assigns a string to foo, overwriting the previous value (the function)
console.log(foo) logs the string
foo() throws an error because a string is not a function
functions declaration are run before everything else
(function() {
function foo() { //Function declaration
return 'hello';
}
console.log(typeof foo); // (A) function pointer
console.log(typeof bar); // (B) undefined
var foo = 'hi',
bar = function() { //Function expression
return 'world';
};
console.log(foo); // (C) hi
foo();// (D) error
})();
Imagine your program looks like this, because foo() is the first thing to run
In the beginning you variable foo is hoisted but without initialisation, so it's undefined. Then it's overwritten by the function declaration. That's why typeof returns Function. Then the value is assigned to it ('hi'), so trying to call the function fails.
In the case of bar, you are using the Function expression syntax (var bar = function()) rather than Function decalration (function bar()), so bar is hoisted as an undefined variable and later a value is assigned to it.
I understanding how hoisting in javascript occurs, functions are hoisted before variables, and only the declarations are hoisted. But When I came across hoisting inside if/else conditionals, like this one:
foo(); // "b is the output"
var a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
Now the conditional is true, so according to the if block, a should have been the output, but due to some kind of hoisting I assume b is the output.
So how is b the output?
In JavaScript, variables, function expressions and function declarations are hoisted to the top of the scope.
Function declarations defines a named function variable without requiring variable assignment.
And important to know is that the entire body of the function declaration gets hoisted up the scope.
E.g.
function outerFunction() {
console.log(typeof functionDeclaration); // outputs "function"
function functionDeclaration() {
// ... function body
}
}
This is because, because of hoisting the code runs like so:
function outerFunction() {
function functionDeclaration() {
// ... function body
}
console.log(typeof functionDeclaration); // outputs "function"
}
In your case, the last function declaration for foo is hoisted to the top of the scope overriding all the other function declarations. Therefore, it logs "b".
Variables and function expressions, however, get hoisted without their assigned values.
E.g.
function outerFunction() {
console.log(functionExpression); // outputs "undefined"
var functionExpression = function () {
// ... function body
}
}
Runs more like so,
function outerFunction() {
var functionExpression = undefined;
console.log(functionExpression); // outputs "undefined"
functionExpression = function () {
// ... function body
}
}
(Ignoring the slightly dodgy behaviour that certain old browsers may have had:)
In Javascript, function statements are scoped within the containing function (or globally if there is no containing function), they're not scoped within an if or else or loop block. So you can't declare a function conditionally in that manner (it can be done another way; see below). And if you declare more than one function with the same name in the same scope the later one will overwrite the first one.
So what happens with your code is:
Both function statements are hoisted, but
They both have the same name so the first is overwritten by the second.
The variable, a is created but not yet assigned a value.
The foo() statement is executed, logging "b"
a is assigned the value true.
The if is executed. The condition is true, but neither the if nor else branches actually do anything because they don't contain statements other than the function declarations that were hoisted earlier.
If you want to create functions conditionally you have to declare a variable and then assign a function expression to it. And then you can not call the function until after that assignment:
var foo;
var a = true;
if(a)
foo = function() { console.log("a"); };
else
foo = function() { console.log("b"); };
foo();
The is not the correct behavior anymore in modern JS browsers! The modern browsers will compile and hoist the mentioned code like this:
// hoisting (treat foo declarations as a normal variable declaration inside if statement)
var a;
var foo;
// now the assignment
foo(); // TypeError (foo = undefined)
a = true;
if (a) {
function foo() { console.log("a"); }
}
else {
function foo() { console.log("b"); }
}
This is a unspecified behavior, different browser behaves diffrently.
MDN explain
In chrome & firefox, it will output foo is not a function.
And in safari, it will output b.
another doc of MDN
david sharif made a JS quiz which pretty much looks like-
var foo=1;
function bar(){
return foo;
foo=10;
function foo(){}
var foo =5;
}
typeof bar();//?
In my understanding, functions are hosited first and then variable declared inside. the hosited form of the function would be something like (correct me if i am wrong)-
var foo=1;
function bar(){
function foo(){}
var foo;
return foo;
foo=10;
foo =5;
}
typeof bar();//?
why typeof bar() is function not undefined?
Is this because of, at the time of function execution, it finds the first foo (which is a function) and returns happily without continuing search. Or something else?
Appreciate your time.
I found the answer in David Shariff blog.
"Shamelessly copied from his blog"-
Even though foo is declared twice, we know from the creation stage that functions are created on the activation object before variables, and if the property name already exists on the activation object, we simply bypass the declaration.
Therefore, a reference to function foo() is first created on the activation object, and when we get interpreter gets to var foo, we already see the property name foo exists so the code does nothing and proceeds.
If this sound like greek, read the whole blog
The Function Declaration "shadows" the var statement.
Paste this in to your console:
var foo = function(){}
var foo
typeof foo
This is how the code "looks like" to the Interpreter after compiletime:
var bar = function bar(){
var foo = function foo(){}
foo
return foo;
// never reached
foo = 10;
foo = 5;
}
var foo;
foo = 1
typeof bar();//"function"
Function declarations are evaluated upon entry into the enclosing scope, before any step-by-step code is executed. The function's name (foo) is added to the enclosing scope (technically, the variable object for the execution context the function is defined in).
Example 1
From this example wecan see that even we are declaring foo after the return statement, we can still get foo returned.
function bar() {
return foo;
function foo() {} // this will get initialized before the return statement.
}
console.log(typeof bar()); // this will be function
Example 2
From this example we can see that if we are declaring our variables in a normal way after the return statement, they will not execute(assigned).
Declare function after return.
function bar() {
return foo;
var foo = function() {} // this will not get assigned
}
console.log(typeof bar()); // this will be undefined
Declare number after return
function bar() {
return foo;
var foo = 12; // this will not get assigned
}
console.log(typeof bar()); // this will be undefined
Example 3
Now let's walk through a messier example line-by-line.
function bar() {
return foo;
function foo() {} // <-- initialize foo as a function
var foo = 11; // <-- this will not get assigned
}
console.log(typeof bar()); // function
I hope the above example will not only answer you question but also give you a better understanding of:
var foo = function() {} vs function foo() {}
Does a Javascript self executing function work like a compiled program. I.e can you declare some function after a named anonymous function within a self executing function and have the named anonymous function locate the other function at runtime? I.e why does the following work?
I'd thought that you could not hoist named anonymous functions as they are only created during runtime so perhaps the self executing function "compiles" the code to make the named anonymous function available to the function that calls it!!
(function(){
var myFunc = function(){
var bar = "Bar";
return myFunc2() + bar;
}
function myFunc2(){
return "Foo ";
}
})()
or even
(function(){
function myFunc(){
var bar = "Bar";
return myFunc2() + bar;
}
var myFunc2 = function(){
return "Foo ";
}
window.fooBar = myFunc();
})()
console.log(fooBar);
That particular example works because myFunc2 is never called because myFunc is never called.
In general though, the normal rules for JS scope, hoisting and timing apply:
A variable must be populated before you use it, not before you define a function that will use it when called.
Lets see what actually happens in your code.
1.you have a function that performs a variable assignment:
var myFunc = ;
2.you declare a function. (But don't yet invoke it)
3.you assign myFunc to window.foobar.
4.And you invoke the function you were defining.
Now, these steps happen:
myFunc gets a function as its value.
myFunc2 gets defined.
window.foobar gets the result of calling myFunc().
so what happens is, myFunc() returns the result of invoking myFunc2() and appends its result to bar.
Thus, the value of window.foobar will be "foobar".
(no, this is not how compiled programs work)
(function(){
var myFunc = function(){
var bar = "Bar";
return myFunc2() + bar;
}
function myFunc2(){
return "Foo ";
}
})()
After some hoisting this becames:
(function(){
var myFunc;
function myFunc2(){
return myFunc2() + bar;
}
myFunc = function(){
var bar = "Bar";
return "Foo ";
}
})()
And actually this will work if you call myFunc(); and log the returned value from myFunc2 you will get Foo Bar.
When hoisting named anonymous functions(which is actually function expression), only
var myFunc (= undefined); is hoisted. Then the assignment stay at the same level.
Also you cant refer this function as self execution function(because self executed function is actually recursion). This is Immediately Invoked Function Expressions.
And #Quentin said the rest: A variable must be populated before you use it, not before you define a function that will use it when called.
If I do this in my <head> tag:
<script type="text/javascript" src="foo.js"></script>
And inside foo.js I do this:
var foo = new Foo();
function Foo()
{
//code here
}
Would this code reliably instantiate the variable foo even though its included above the function definition, or should I move it instead to the bottom of the file, like this:
function Foo()
{
//code here
}
var foo = new Foo();
Your example will work in any browser that follow the ECMAScript standard (all do at least with regards to this question).
See sections 10.3-10.5 of the specification.
First the local scope is set up and just thereafter the function body is actually run.
Read 10.5 (the section is really not very long) to understand why #meder's answer is right.
If you don't want to read the specs yourself:
10.5 tells to declare variables in that order (overwriting if a some name occurs twice):
Inheriting from outer scope = setting will affect the outer scope:
Variables of the surrounding scope.
The own function name.
Local scope = setting won't affect the outer scope:
The parameters (left to right).
The arguments object.
Declare all the inner variables (not overwriting the current value if any, undefined if none, yet)
All in all:
Returns the function x itself:
function x() {
return x;
}
Returns the parameter x:
function x(x) {
return x;
}
Returns the inner function x:
function x(x) {
return x; // the return does no harm, x is already set
function x() {} // before the actual body is evaluated
}
Also returns the inner function x:
function x(x) {
var x; // in this case a no-op
return x;
function x() {}
}
Returns 42:
function x(x) {
var x = 42; // overwrite x in local scope
return x;
function x() {}
}
Returns the second argument:
function x(x,x) { // assign left to right, last one "wins"
return x; // arguments[0] would still name the first argument
}
Returns 2 when x is called the second time, as x is set to the inner function:
function x() {
x = function() { return 2; } // set x in outer scope
return 1;
}
It's only necessary to move it above if you define it via var, such as:
var Foo = function(){};
var foo = new Foo;
Otherwise, to my knowledge the interpreter reads function definitions in advance.
As far as i know, JS does this to your code due to hoisting:
var foo; //var declarations hoisted up
function Foo(){ //function declarations hoisted up
//code here
}
foo = new Foo(); //the operation
so it should be fine. However, I'd not rely solely on hoisting because, for me at least, it's hard to debug when declarations are all over the place. For readability, order the code this way:
variable declarations
functions
operations
code 1:
console.log(foo); //undefined
var foo = new Foo();
console.log(foo); //Foo
function Foo(){
//code here
}
console.log(foo); //Foo
//acts like:
var foo; //var declaration hoisted up
function Foo(){} //function declaration hoisted up
console.log(foo); //undefined
foo = new Foo();
console.log(foo); //Foo
console.log(foo); //Foo
code 2:
console.log(foo); //undefined
function Foo(){
//code here
}
console.log(foo); //undefined
var foo = new Foo();
console.log(foo); //Foo
//acts like:
var foo; //var declaration hoisted up
function Foo(){} //function declaration hoisted up
console.log(foo); //undefined
console.log(foo); //undefined
foo = new Foo();
console.log(foo); //Foo