This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 1 year ago.
There below two codes print different outputs, despite the inner function not being called.
var a = 1;
function foo(){
a= 2;
}
foo();
console.log(a); // 2
But if I add a function with the same name, the output is different. Although I am not calling the a()
var a = 1;
function foo(){
a= 2;
function a(){
a = 3;
}
}
foo();
console.log(a); // 1
Should not it be 2? Why it logs 1?
Because an identifier named a is declared directly inside the foo function, assignments to variables named a inside the foo function will reference that (local) identifier, and not any possible outer variables named a. It's like:
var a = 1;
function foo(){
// there an identifier named `a` initialized in this scope
var a;
// function declarations are hoisted
a = function a(){
a = 3;
}
// assignment to local identifier `a`
a= 2;
}
foo();
console.log(a); // 1
Related
For example:
(function foo() {
var a = 3;
console.log(a);
});
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
obj.a(); // 2
foo(); // ReferenceError: Not Defined
How is that I can access a function expression within obj, but not in the global object?
Edits: for cohesion and clarity
You're confusing a couple of different things here.
Your first statement is a function expression, not a function declaration:
(function foo() {
var a = 3;
console.log(a);
});
This happens to be a named function expression ("foo"), but it does not introduce a variable foo in this scope. If you wanted to introduce foo so that it can be called again, you need either a function declaration...
function foo() {
var a = 3;
console.log(a);
}
foo();
or, you need to assign the function expression to a variable:
var foo = function () {
var a = 3;
console.log(a);
}
foo();
Your next bit of code, the object declaration, effectively does this by assigning the function expression to a variable, obj.a:
var obj = {
a: (function foo() {
var a = 2;
console.log(a);
})
};
The error in your thinking here is due to confusion around foo. In both cases, foo is the name of the function, but it's not actually relevant to invoking the function. You should drop the foo because it's only confusing things.
In essence, your first snippet is equivalent to:
(function () { alert('x'); });
This line of code defines an anonymous function, but does nothing with it. The function exists briefly, is never invoked, and then is lost, because it is not assigned to anything.
Your second snippet is equivalent to:
var x = function () { alert('y') };
This code defines a variable, x, and assigns a function to it. The function can then be invoked with x(), and the function remains available as long as x is in scope.
Your original question is:
How can an object access function expression?
Which doesn't really make sense. The object can't "access the function expression", it just contains a property to which a function has been assigned, while the snippet outside the object did not retain the function in a way that would allow you to invoke it.
Please explain what is the logic behind this two types of behaviour to understand easily.
var a = 10;
function foo(){
a = 20;
}
foo();
console.log(a);
Prints---> a = 20;
var a = 10;
function foo(a){
a = 20;
}
foo();
console.log(a);
Prints---> a = 10;
Because of the scope
In Javascript, when you assign a parameter in a function you define it in the scope of that function, regardless if a variable already exists with the name in the outer/global scope.
Update:
It is worth mentioning that with ES6's arrow functions you could still access the outer var if your function was defined in a parent class or function, using the this keyword.
Example
class Bar {
this.a = 10;
this.foo = function(a) {
this.a = 20;
};
this.foo2 = (a) => {
this.a = 20;
};
}
Not exactly the same but it is about scopes
Check the following code snippet
var a =10;
var b = a;
function foo(a){
// a here woukd refer to the parameter a and not the global variable, since it got overridden
console.log(a, b);
a= 20;
}
foo();
// prints the global variable a
console.log(a);
function bar(){
console.log(a, b);
// overrides the global variable a
a = 20;
}
bar();
// prints the global variable a
console.log(a);
the first one is because of global scope
var a =10;
function foo(){
a= 20;
}
here varieble a is accesed globaly and updated from inside the function global varieble can access every place
in the 2nd example just passing a referece of varieble a as a parameter and inside the function the recived parameter value get changed
var a =10;
function foo(a){
a= 20;
console.log(a)
}
foo();
console.log(a);
please run the second example of code in console then you can understand the change.
In the first example a in the function is replacing the first declaration of a outside the function because you're not scoping it locally with var (or let or const).
In the second example the function accepts a as an argument so it becomes scoped locally to the function. Note that this occurs even if a isn't actually passed into the function (and is therefore undefined).
A good article on scope and context that might be of some use to you.
In javascript, function variables has its own scope, if you used var,let,const or using variable as provided in formal parameters in function. if you don't use any of above variable's scope will be global.
This question already has answers here:
Javascript function scoping and hoisting
(18 answers)
Closed 6 years ago.
Hi I am trying to understand the JavaScript fundamentals, and stuck in one condition.
var foo = 1;
function bar(){
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
Here alert(foo), will give me 1, and I know after return statement, function foo() will not execute. But now if change the code:
var foo = 1;
function bar(){
foo = 10;
return;
}
bar();
alert(foo);
In bar function, If I will remove function foo(). then alert(foo) will give me 10
Please help, if someone can explain me why?
This is called Javascript hoisting
I will try to explain it in details.. This is what we have
var foo = 1;
function bar(){
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
The interpreter will rewrite this as
var foo = 1;
function bar(){
function foo(){} // this is also equal to var foo = function(){};
foo = 10;
return;
}
bar();
alert(foo);
So now explaining you the hoisted code.
var foo = 1; // global variable;
function bar(){
var foo = function(){}; // foo is local variable of type function
foo = 10; // foo is changed to hold a number
return;
}
bar();
alert(foo); // you alert global variable.
As you can see if the code function foo(){} is present it is treated as a local variable within the bar() scope and any change to the foo is treated as a local variable change..
When you have function foo(){} in your bar() you are not even touching the global variable.. hence alerts 1.
When you don't have function foo(){} you are touching the global variable and hence alerts 10.
Now I hope you understand the output..
I know after return statement ,function foo() will not execute.
That's not true.
Function declarations are hoisted.
function foo(){} creates a local variable called foo (assigning the new function to it) and then foo = 10 overwrites it. You never test the value of that foo variable though.
In bar function , If I will remove function foo(). then alert(foo) will give me 10
You no longer have a local variable called foo so you are overwriting the global variable with the same name.
Compare:
(function() {
console.log("Version 1");
var foo = 1;
function bar() {
console.log("At top of bar, foo is " + foo);
foo = 10;
console.log("After assignment in bar, foo is " + foo);
return;
function foo() {}
}
bar();
console.log("Global foo is " + foo);
}());
(function() {
console.log("Version 2");
var foo = 1;
function bar() {
console.log("At top of bar, foo is " + foo);
foo = 10;
console.log("After assignment in bar, foo is " + foo);
return;
}
bar();
console.log("Global foo is " + foo);
}());
When you write this function :
function bar(){
foo = 10;
return;
function foo(){}
}
The javascript read this :
function bar(){
function foo(){}
foo = 10;
return;
}
The function foo is created into your local function bar. And when you write foo = 10,You overwrite the function foo in the local scope and not the global variable.
So your alert give you 1 because you never update the global variabe.
The problems here are hoisting and closure .
The declaration function foo(){} is hoisted, meaning in this case, even though it is written at the end of the function, it will be available everywhere within the scope, including before it's definition.
if function foo(){} IS NOT present, the statement foo = 10; overwrites the foo defined in the global scope. Therefore the global foo === 10.
If function foo(){} IS present, the statement foo = 10; just overwrites the function foo in the local scope, the global foo won't get touched hence global foo === 1
var foo = 1;
function bar(){
console.log(typeof foo) // function
return;
function foo() {}
}
bar();
alert(foo);
Opposed to:
var foo = 1;
function bar(){
console.log(typeof foo) // number
return;
// function foo() {}
}
bar();
alert(foo);
So basically what is happening is as if you have declared var foo = 10
because function declaration in javascript are hoisted up top
complier sees your code as follows .
var foo = 1;
function bar(){
var foo;
foo = 10;
return;
function foo(){}
}
bar();
alert(foo);
so in fact foo = 10 never overwrites the global foo;
it is kept local to the function .
so alert will get passed the global one .
In addition to my previous answer in the same thread I am
adding another answer to put in more details about the Hoisting
feature in JavaScript as the previous answer is already accepted by the OP for its content.
First lets get comfortable with what scoping is
Scoping in JavaScript
One of the sources of most confusion for JavaScript beginners is scoping. Actually, it’s not just beginners. I’ve met a lot of experienced JavaScript programmers who don’t fully understand scoping. The reason scoping is so confusing in JavaScript is because it looks like a C-family language. Consider the following C program:
#include <stdio.h>
int main() {
int x = 1;
printf("%d, ", x); // 1
if (1) {
int x = 2;
printf("%d, ", x); // 2
}
printf("%d\n", x); // 1
}
The output from this program will be 1, 2, 1. This is because C, and the rest of the C family, has block-level scope. When control enters a block, such as the if statement, new variables can be declared within that scope, without affecting the outer scope. This is not the case in JavaScript. Try the following in Firebug:
var x = 1;
console.log(x); // 1
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
In this case, Firebug will show 1, 2, 2. This is because JavaScript has function-level scope. This is radically different from the C family. Blocks, such as if statements, do not create a new scope. Only functions create a new scope.
To a lot of programmers who are used to languages like C, C++, C#, or Java, this is unexpected and unwelcome. Luckily, because of the flexibility of JavaScript functions, there is a workaround. If you must create temporary scopes within a function, do the following:
function foo() {
var x = 1;
if (x) {
(function () {
var x = 2;
// some other code
}());
}
// x is still 1.
}
This method is actually quite flexible, and can be used anywhere you need a temporary scope, not just within block statements. However, I strongly recommend that you take the time to really understand and appreciate JavaScript scoping. It’s quite powerful, and one of my favorite features of the language. If you understand scoping, hoisting will make a lot more sense to you.
Declarations, Names, and Hoisting
In JavaScript, a name enters a scope in one of four basic ways:
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;.
Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter.
Function parameters and language-defined names are, obviously, already there. This means that code like this:
Ex:
function foo() {
bar();
var x = 1;
}
is actually interpreted like this:
function foo() {
var x;
bar();
x = 1;
}
It turns out that it doesn’t matter whether the line that contains the declaration would ever be executed. The following two functions are equivalent:
function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}
function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}
Notice that the assignment portion of the declarations were not hoisted. Only the name is hoisted. This is not the case with function declarations, where the entire function body will be hoisted as well. But remember that there are two normal ways to declare functions. Consider the following JavaScript:
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
In this case, only the function declaration has its body hoisted to the top. The name ‘foo’ is hoisted, but the body is left behind, to be assigned during execution.
That covers the basics of hoisting. The complete 100% credit of this answer goes to ben cherry. I didnt want to post this link in my answer because the links might break and I found this completely informative and a must read for any javascript developer.
This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 8 years ago.
var a = 2;
var b = function(){
console.log(a);
var a = 1;
};
b();
When I call b, it prints undefined. What is the reason?
Inside a function, var declares a function-scoped variable. That means it's visible to the function. The entire function. That means you are print out the variable before assigning a value to it.
var a = 123;
(function () {
a = 456; // Changes the function's "a"
console.log(a); // Outputs the function's "a": 456
var a; // At compile-time, declares a function variable named "a".
})();
console.log(a); // Outputs the global "a": 123
Along the same line, repeating the declaration doesn't do anything. The following prints out 123.
(function () {
var a = 123;
var a;
console.log(a); // 123
})();
The var a in your code is a variable declaration that declares a variable within the scope of its containing function. Due to variable hoisting, variable declarations (like var a) are hoisted to the top of their containing function. While any declaration is hoisted, assignments to that variable are not hoisted, Thus, your code is equivalent to:
var a = 2;
var b = function(){
var a; // hoisted declaration; declares `a` within this function scope
console.log(a);
a = 1; // not-hoisted assignment
};
b();
Since a declared variable is undefined until it is given a value, this code logs undefined.
You have this:
var a = 2;
var b = function(){
console.log(a);
var a = 1;
};
During the run time it becomes:
var a = 2, b;
b = function(){
var a; // new variable declaration with no value assigned
console.log(a); // You used it new "a" without assigning any value
a = 1;
};
Inside the function the a is a new variable because of var keyword and JS is taking this new a in account which is undefined not the global a. Tow variables with same name, one is outside the function (in global scope) and another is inside the function. Since there is a new variable available inside the function so it's being used in console.log(a) but no value assigned.
You may read JavaScript Scoping and Hoisting and var on MDN.
This question already has answers here:
What is the difference between a function expression vs declaration in JavaScript? [duplicate]
(5 answers)
var functionName = function() {} vs function functionName() {}
(41 answers)
Closed 8 years ago.
What is the difference between
var a = function() {}
and
var a = function b() {}
The latter, b is undefined?
The second one is a named anonymous function - the name will appear in a stacktrace (otherwise in the stacktrace you''ll see just "anonymous function")
The first is an anonymous function expression and the second a named function expression, both valid in Javascript.
For example, it can be used for recursion without arguments.callee (deprecated and not permitted in strict mode), because it refers to itself, no matter where. The scope of the reference is local only to inside the function, that is it isn't accessible globally:
var a = function b(){
return b;
};
function c() {
return c;
}
var d = function e() {
return e();
};
d(); // maximum call stack size exceeded :P
var f = c;
c = null;
f(); // null
a(); // function
b();// undefined not a function
b; // not defined
a()(); // same function again
var a = function() {}
Function name can be omitted. In this case function name is omitted. These functions are called anonymous functions.
Read about javascript scope and anonymous function advantages and disadvantages for details.