var abc = function() {
console.log(1);
}
function abc() {
console.log(2);
}
abc();
I am expecting that it will console 2, but no it will console 1 because of
function and variable hoisting.Anybody who want to make it more clear.
In JavaScript, a name enters a scope in one of four basic ways and the order of hoisting follows following order...
Language-defined: All scopes are, by default, given the names this and arguments
Formal parameters: Functions can have named formal parameters, which are scoped to the body of that function
Function declarations: These are of the form function foo() {}
Variable declarations: These take the form var foo;
Reference: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
In your case the 1st function is type 4 and the second function is type 3. Therefore the second function is hoisted first assigning the function reference to abc. And then the first function is hoisted reassigning the reference to abc. Your code is compiled in following order,
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
}
abc();
Note that only declarations are hoisted. Assignments are not hoisted.
var bar = 'test';
var foo = function(){/*foo 1*/};
var foo;
function foo(){/*foo 2*/}
alert(foo);
will be complied in this order,
function foo(){/*foo 2*/} //function declaration
var bar; //variable declaration
var foo; //variable declaration
bar = 'test';
foo = function(){/*foo 1*/};
alert(foo);
var hoisting
the Key to understanding how scope in JavaScript works is understanding the concept of hoisting.
Because variable declarations (and declarations in general) are
processed before any code is executed, declaring a variable anywhere
in the code is equivalent to declaring it at the top. This also means
that a variable can appear to be used before it's declared. This
behavior is called "hoisting", as it appears that the variable
declaration is moved to the top of the function or global code.
console.log("function hoisting:::: ",abc()); /* log = 2 we are calling the function(hoisting)*/
var abc = function() {
console.log(1);
};
console.log("var:::: ",abc()); /* log = 1*/
function abc() {
console.log(2);
}
abc(); /* log = 1*/
console.log("function:::: ",abc()); /* log = 1*/
So in your case you are not calling the function, to call the function log it on the top.
this is how the javascript engine interprets it
function abc() {
console.log(2);
}
var abc;
abc = function() {
console.log(1);
};
abc();
REF: JavaScript Scoping and Hoisting
If you're simply asking why the function abc isn't the one being executed despite it being declared most recently, it's because, In Javascript, functions are hoisted to the top of the current scope.
That means your code is morphed into something like the following:
function abc() { console.log(2); }
var abc = function() { console.log(1); }
abc();
That means, when it comes time to call abc, the "active" one is the one that logs 1.
One of the best articles I ever found on this behaviour was the one over at adequately good.
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.
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())
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
i'm learning about functions. i'm confused in one scenario.
suppose i have three functions
<script>
var fnRef = function() {
console.log("i'm function with no name but refered to fnRef");
};
var funRef2 = function test() {
console.log("im test reffered to funRef2");
};
function test2() {
console.log("i'm test2 named function")
};
</script>
fnRef, fnref2 and test2 will be assigned to window as a property as fnRef and fnRef2 are variable and test2 is named function that act as variable.
but why test2 is not assigned to the global object(window) when refered by funref2? and why i'm not able to execute test(); can someone tell me what is happening in detail.
The named function expression is useful so you can access the function inside it's own scope without using arguments.callee, and it also makes it easier when debugging as the name can be seen in stack traces, breakpoints etc.
This name is then local only to the function bodys scope, meaning
var test1 = function test2() {
if (something) test2(); // available in this scope only
}
test2(); // not here
You can't call the function by it's name, only by the variable it's assigned to, as the functions name is limited to the functions scope when it's a function expression.
When defining a function declaration, the name is assigned to the current scope, and hoisted, so this
var bar = test();
function test() { return 'foo'; }
is more or less turned into this
var test = function() { return 'foo'; }
var bar = test();
Is javascript code read from the top down?
In other words if I have:
function Color(){
}
function Weather() {
}
If I wanted to incorporate some type of weather object inside the Color function would it be possible since Weather is defined afterwards?
The function Color won't know about Weather as it's being parsed, but it will once it is called. For example:
// Since variable declarations are hoisted to the top,
// myVar will be undefined (same as simply saying "var myVar;")
console.log(myVar); // <-- undefined
var myVar = 5;
console.log(myVar); // <-- 5
// test2 hasn't been defined yet, but it doesn't matter
// because test isn't being executed
var test = function() {
test2();
}
// This will throw an error: undefined is not a function
// because test2 isn't defined
test();
var test2 = function() {
alert("test2");
}
// This won't throw an error
test();
Essentially, you should execute after all functions have been defined. However, if you use the function functName() {} syntax, then it is hoisted just like a var statement.
function test() {
test2();
}
// Works!
test();
function test2() { alert("test2"); }
JavaScript is parsed "top-down" and Function Declarations are hoisted constructs - see var functionName = function() {} vs function functionName() {}. Parsing happens before the JavaScript execution itself starts; the following thus covers the evaluation semantics1.
Given the effect of function hoisting, the following code is valid, although it seems like it might not be:
function a(){
return b();
}
alert(a()); // alerts "b", even though "b comes later"
// This declaration IS hoisted
function b() {
return "b";
}
However, considering that even when using "var fn = .." (when the assignment is not hoisted) the ordering usually doesn't matter because the evaluation of the assignments happens before the usage:
var a = function () {
return b();
}
// alert(a()); <- this would fail, because b is not assigned yet
// This assignment is NOT hoisted
var b = function () {
return "b";
}
// But b is assigned before here, meaning that the order of the constructor
// functions still Just Doesn't Matter.
alert(a());
As such, in the case where there are two constructor functions (e.g. Color and Weather) which are [mutually] dependent, it doesn't matter where they are located in the same scope relative to each other.
1The thing that matters is the expression representing the dependency is resolvable when evaluated (which is relative to the evaluation code, but not related to the parsing/placement order of the functions).
so basically yeah you can implement something to a function that appears in a previous code.
hole this helps you understand it better.
var weather = function() {
if (weather === red) {
console.log("weather is represented by the color red");
}
else {
console.log("Not the right color");
}
};
weather(red);