I was exploring scopes in javascript and came to know this problem. I don't understand how this problem is working.
function checkType() {
return foo;
foo = 10;
function foo() {};
var foo = 11;
};
console.log(typeof checkType())
My question is this how does javascript compiler decide to return function not variable. Any reference or explanation are welcome.
This is how the compiler will compile the above code..
function checkType() {
var foo = function() {}; /* function will be hoisted to the top,
and will be assigned to the variable as
the name is the same for the two.. */
return foo;
// Code will never reach here as you are returning before this
foo = 10;
foo = 11;
};
console.log(typeof checkType());
Functions which are defined using function() syntax will be hoisted, in this case, the nested function will be hoisted insde the checkType() and hence, the checkType() returns the function instead of the integer.
Note: Because the function was defined using function(){} syntax, it
was hoisted to the parent function scope, else, if the function was
defined using var foo = function() {} then the hoisting would not
have worked in the same way, your function would've returned undefined instead.
More reference on Scoping & Hoisting
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting/
First all the function declarations are hoisted in a scope. So first of all the code moves the variable foo to the top of the scope and initialize its value to function.
The second declaration of variable is not hoisted because the function declaration is already hoisted. So the code is same as
function checkType() {
var foo = function(){}
return foo;
foo = 10;
foo = 11;
};
When we run a code there are two phase of it first is creation phase in this phase the syntax parser will read the code and hoist the function and variables, and second phase is execution phase in which the values are assigned to hoisted variables,
A point to note here is function are stored in memory during creation phase as it is where as the variables are hoisted but values
are not initialized ( which will be assigned during execution phase )
Compiler will treat your code like this after hoisting
function checkType() {
var foo = function() {}; //hoisted function
return foo;
foo = 10;
foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())
If you define your function as variable than it will be hoisted only but will not be initialized with value, you can see the below example
function checkType() {
return foo;
foo = 10;
var foo = function foo() {};
var foo = 11;
};
console.log(typeof checkType(), '\nRturned value from function --->', checkType())
Related
I was reading Kyle Simpson book: https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/scope%20%26%20closures/ch4.md#functions-first.
But I don't fully understand this line "Notice that var foo was the duplicate (and thus ignored) declaration, even though it came before the function foo()... declaration, because function declarations are hoisted before normal variables."
Let's say this is the code:
console.log(foo); // The output is: foo() { return 2; }
function foo() {
return 1;
}
function foo() {
return 2;
}
var foo = 3;
I want to visualize what would be the output in JS Engine after Memory Creation phase. Will it be like this?
function foo() {
return 2;
}
console.log(foo);
If yes, why var foo = 3; was ignored? There is no duplicate for var in the snippet. If no, can anyone please help me visualize what would be the output in JS Engine after Memory creation phase?
Thanks
I think the text refers to
// scope creation
var foo; // the name was declared. Thrice.
foo = undefined; // from the var
foo = function foo() { return 1 }; // from the first declaration
foo = function foo() { return 1 }; // from the second iteration
// execution
console.log(foo);
;
;
foo = 3;
where foo is initialised with undefined due to the var foo declaration, but then gets overwritten by the initialisation value from the function foo declaration which takes precedence - regardless of the order in which the declarations appeared in the code, function declarations overrule var declarations.
Function declarations
Declare a variable with the same name as the function (this is hoisted)
Assign the function to that variable (this is hoisted)
var statements with associated assignments
Declare a variable with that name (this is hoisted)
Assign the value to that variable (this is not hoisted)
var foo = 3 is not ignored.
The variable declaration (var foo) is ignored because the earlier function declarations already declared that variable. (i.e. because it duplicates the declaration of foo).
foo = 3 is not ignored and does assign 3 to foo … it just does so after your console.log statement runs because it isn't hosited.
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() {}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why can I use a function before it's defined in Javascript?
As would be expected, the following code throws an error because Foo is not defined:
window.Foo = Foo;
Also as expected, this throws the same error:
window.Foo = Foo;
Foo = function() {
...
};
Curiously, this works just fine:
window.Foo = Foo;
function Foo(){
...
};
How is this possible? Isn't JavaScript interpreted line-by-line?
Hoisting is only part of the story here.
First, to explain hoisting:
When you use var in a JavaScript program, you declare a variable. Wherever that variable is declared in a JS scope, it is hoisted to the top of that scope. JavaScript has only Global or Function scope; in the case of a function
function hoistAway() {
console.log(a);
var a = 5;
}
is equivalent to
function hoistAway() {
var a;
console.log(a);
a = 5;
}
As you can see, the declaration is hoisted, but the initialization is not. Thus, this code would log undefined on the console, rather than 5. However, it would be satisfied that a exists.
When you don't use var, the declaration is not explicit, so it doesn't get hoisted. Thus:
function hoistAway() {
console.log(a);
a = 5;
}
will result in an error message.
In your examples:
window.Foo = Foo;
Foo was never declared, so you get an error.
window.Foo = Foo;
Foo = function() {
...
};
Again, Foo was not declared, so no hoisting. For the record:
window.Foo = Foo;
var Foo = function() {
...
};
will not throw an error. However, only the declaration is hoisted, so if you did something like
var bob = {};
bob.Foo = Foo;
var Foo = function() {
...
};
then bob.Foo would be undefined. The special case of window.Foo = Foo is weird because Foo and window.Foo are the same in the Global scope.
Finally:
window.Foo = Foo;
function Foo(){
...
};
works, because function declarations (as opposed to function expressions) are also hoisted; both the name and the definition gets hoisted, so this would work as intended.
The script is parsed first, allowing your code to call functions that are defined later on.
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
Can a private variable within a child scope be set to the value of a same-named private variable from its parent scope?
Consider the following:
var foo = 10;
function bar () {
var f = foo, foo = f;
return foo;
}
bar() // Returns 10
Can this be done without using the placeholder variable f?
var foo = 10;
function bar () {
var foo = foo;
return foo;
}
bar() // Want 10 but returns undefined.
I would like a solution that does not pass any arguments to bar. I realize that this isn't important for any reason other than aesthetics.
In the second case, global variable is not visible since there is a local variable having the same name. In other words, local variable hides the global variable.
var foo = foo;
The declaration of foo ends only after reaching ;. But trying to initializing foo to foo itself is undefined since it hasn't reached it's ending point of declaration.
Yes, but you'll have to explicitly reference foo off of the parent scope. Usually that will just be this, but you'll have to be careful in situations where your function may have been invoked via apply or call. This, for example, should work:
var foo = 10;
function bar () {
var foo = this.foo;
return foo;
}
bar(); // 10
Edit: I need to make a correction, per #Felix' comment. this will indeed usually refer to the global scope, rather than the parent scope. Consider this for example:
var x = 'global';
(function () {
var x = 'inner';
(function() {
var x = this.x;
console.log(x); // 'global'
})();
})();