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() {}
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.
This question already has answers here:
Javascript variable and function hoisting
(3 answers)
Closed 6 years ago.
function bar() {
return foo;
foo = 10;
function foo() {}
var foo = 11;
}
console.log(typeof bar());
typeof bar returns function?!
why not number?
JS functions are executed in two passes three passes. First, the engine walks through the code, looks for function declarations and hoists them (=moves them to the top), second, it hoists variable declarations (unless the same name is already hoisted), finally it runs the "normalized" code.
In your snippet, the engine picks function foo and moves it to the top of the function. The subsequent var foo is ignored.
This results in the following "normalized" code:
function bar() {
function foo() {}
return foo;
foo = 10;
foo = 11;
}
which explains your results.
Reference: Declaration Binding Instantiation, notice steps 5 and 8.
return foo just references to function foo() {} so it's returning Function
function bar() {
return foo; // function foo() {}
foo = 10;
function foo() {}
var foo = 11;
}
alert(typeof bar()); // function
another scenario
function bar() {
return foo; // returns foo undefined as no value is assigned
foo = 10;
var foo = function () {} // referenced to variable
var foo = 11;
}
alert(typeof bar()) // undefined
here it will return number
function bar() {
foo = 10;
return foo; // 10
function foo() {}
var foo = 11;
}
alert(typeof bar()); // number 10
this too will return a closure function which returns a number
function bar() {
foo = 10;
return function () {
return foo
}
var foo = 11;
}
alert(typeof bar()()); // number 10
You messed with return :).
It is not about the priority. It is about the thing you last return from the function. Alter them and see. You get number.
function bar() {
function foo() {}
var foo = 11;
return foo;
foo = 10;
}
alert(typeof bar());
This gives you number.
The reason for this behavior is due to Hoisting in javascript.
When javascript is interpreted, any variable definition is processed first, so in the scope of your function, the actual order of the call is something like this:
function bar {
var foo = 11;
function foo() {}
return foo;
}
The hoisting positions the var foo = 11 declaration first, and then the foo is overwritten by the foo named function. hence return foo returns the function itself, not the numeric value.
This is a good starting point to understand hoisting
The return statement prevents the number assignments from executing, but the function declaration doesn't care.
function bar() {
return foo;
foo = 10; //assignment is never executed
function foo() {} //function definition happens even if code is not executed
var foo = 11; //assignment is never executed
}
console.log(typeof bar());
To test this out, comment out the function foo() {} line. You'll see that bar() returns undefined. The assignment statements define foo even if the statements are not executed, but they don't clobber the value of foo until they are executed (thus leaving the function definition in place).
Fiddle with the code:
https://jsfiddle.net/vwm31faq
Function gets Hoisted to the top of the current scope, hence you code at execution time would look like
function bar() {
var foo;
function foo() {}
return foo;
foo = 10;
function foo() {}
foo = 11;
}
console.log(typeof bar());
I keep on trying to assign a function to a variable and I keep getting a message saying foo is not a function. I am not sure why it is saying that. When I invoke the method by itself it works, but when I assign it to a variable it won't work.
Can anyone please help me figure this out? Thank you!!!
Below is my code:
function Test(){
function foo(){
return "foo";
}
this.bar = function () {
var foo = foo();
console.log(foo);
};
}
var test = new Test();
test.bar();
The culprit is this line var foo = foo();. The statement var foo is redeclaring the local foo variable. By the time you try to access it with foo() it has become an undefined variable.
Rename the variable or the function and everything works correctly.
Following code will work. As Now we are not trying to assign same function variable to variable.
The problem is because JavaScript is function scoped. It is failing because this.bar function will try to evaluate foo first and foo is name of variable in this function so interpreter will try to execute the foo but foo is variable in this scope it will not consider foo mentioned above. Hence it fails.
Where as foo1 will work because when interpreter hits the term foo1 it will look for current scope and all parent scopes and it will get it.
function Test(){
function foo1(){
return "foo";
}
this.bar = function () {
var foo = foo1();
console.log(foo);
};
}
var test = new Test();
test.bar();
Error is at this line
var foo = foo();
Your variable foo has the same name as the function, that hides the function outside.
Renaming it will resolve the error.
var foo1 = foo();
There error you're seeing is from this line:
var foo = foo();
When you use var there you are saying that foo is being defined for the current level of scope (this.bar) - meaning it won't bubble up to Test. You can either rename the variable to something else:
var result = foo();
console.log(result);
or just forgo that variable altogether like this:
console.log(foo());
totally your choice.
If you are learning how to create and work with JavaScript objects, you may want to rewrite your code like so:
// This function constructs the object when called with new
function Test(prop) {
// Some arbitrary property
if (typeof prop === "undefined") {
prop = null;
}
this.prop = prop;
}
// The two functions
Test.prototype.foo = function() {
return "foo";
}
Test.prototype.bar = function() {
var foo = this.foo();
console.log(foo);
}
// Create the object and call foo
var test = new Test('p');
test.bar();
All JavaScript objects inherit the properties and methods from their
prototype. Objects created using an object literal, or with new
Object(), inherit from a prototype called Object.prototype. Objects
created with new Date() inherit the Date.prototype. The
Object.prototype is on the top of the prototype chain.
From: http://www.w3schools.com/js/js_object_prototypes.asp
var bar = function foo() {
foo = 1;
return foo;
};
bar(); // returns function foo()
Why is this happening? I expect this to return 1.
If you want it to return 1, you need to write it like this:
var bar = function() {
foo = 1;
return foo;
};
LVarayut's answer is actually right, you are writing over foo which is in the global namespace. This version declares a local variable foo.
var bar = function() {
var foo = 1;
return foo;
};
Here is a similar question that describes the same behavior...
Function and variable with the same name
And a linked article that describes what is happening...
http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
It's because you have defined foo variable twice, so if you want to return 1, you could change the name of your function to anything else:
var bar = function baz() {
foo = 1;
return foo;
};
bar(); // returns 1
Or you could define a local variable:
var bar = function foo() {
var foo = 1;
return foo;
};
bar(); // returns 1
EDIT:
Here is the answer of your question. The name of a named function expression becomes a local variable and can be only accessed inside the function expression. There is a distinction between the function name and the variable the function is assigned to. The function name cannot be changed, while the variable the function is assigned to can be reassigned.
Read more on MDN.
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