Please let me know the difference between the below two codes.
var a = 1;
function b() {
a = 10;
return;
}
b();
console.log(a);
This prints 10 in console.
whereas the below code prints 1 in console
var a = 1;
function b() {
var a = 10;
return;
function a() {}
}
b();
console.log(a);
Thanks for help.
In the first code there is one global variable 'a' which can be modified by any function and that change would be permanent.
But in the second code, there are two 'a' variable. Lets call them ag (a global) and al (a local). In second code b() function is modifying al (local variable a) not the global variable. But we are printing global variable in console.
Thats why results are varying in both the codes.
It's a metter of scope. In the first a is declared only out of function b, so when you edit a inside function b you are referencing the "outer" a.
In the second snippet you are re-declaring var a inside the function, so when you edit a variable inside the b function you are referencing the latest leaving untouched the "outer" a variable.
You have declared a in your second code inside the function hence the scope(availability) of your variable a persists only till function execution.
Once we return back from the function, local variable a is no more hence outer global a's value is printed.
when you are using var ,its scope will be local to its function.
and without var it will be a global function.
The first example is quite straight-forward: You declare an a variable which your b function closes over. So b sets a to 10.
Your second example is deliberately complex and confusing. You declare an a variable that b closes over, but then shadow it with an a variable inside b. To make matters worse, there's also a function declaration of a that is also in scope in b. The var wins over the function declaration, because function declarations are processed before var statements are. The outer a is completely unaffected by b, so the console.log at the end logs 1.
That's easier to describe with a diagram of sorts:
var a = 1; // <== The declaration `b` closes over
function b() {
var a = 10; // <== The inner `a` variable
return; // <== Returns from `b`
function a() {} // <=== Declaration that was processed immediately
// upon entering `b` (the `return` doesn't affect it
// at all), but which is then superceded by `var a`
}
b();
console.log(a); // Logs 1
Related
Can someone explain why in the following function, I am able to pass an argument to a nested function? My understanding is that it has to do something with closures and scope(which I thought I had a decent understanding of), but I can seem to follow how exactly this argument is being passed.
The below function outputs 1,2 respectively. But how is the return statement doThis() getting the argument/parameter for "a"? I cant figure where/how this is accessed/passed.
function doSomething(){
var b = 1;
return function doThis(a){
console.log(b);//1
console.log(a);//2
}
}
var exec = doSomething();
exec(2);
The function doSomething() returns another function so when you execute
var exec = doSomething();
You can think of that exec as containing the following function
function doThis(a){ // <- takes an argument
console.log(1); // comes from the b argument in the outer scope
console.log(a); // not set yet
}
Thus when you call exec(2) you are actually calling doThis() with an argument 2 which becomes the value of a.
This is a slightly simplified version. To expand on that, the doSomething() function is described as closing over doThis() creating a closure. Conversely, the function doThis() is closed over or inside a closure. The closure itself is simply a limited state around the function:
function doSomething(){ // --> defines the closure
var b = 1; // variable only visible within doSomething()
return function doThis(a){ //<--> function has access to everything in doSomething(). Also defines another closure
console.log(b); // --> accesses the OUTER scope
console.log(a); // <-- comes from the INNER scope
} // <-- end INNER scope
} // --> end OUTER scope
When you execute doSomething() the returned result still retains access to the scope within it, this is why doThis() has access to the value b - it's simply reachable for it. It's similar how you can do
var foo = 40;
function bar(value) {
return foo + value;
}
console.log(bar(2));
Only in this instance any other code will have acces to foo as it's a global variable, so if you do foo = 100 in a different function, that will change the output of bar(). A closure prevents the code inside from being reachable from outside the closure.
When you assign var exec = doSomething();, exec is basically writing:
var doSomething = function(a) {
console.log(b);
console.log(a);
}
It became its own function. So passing in 2 like so exec(2) works like any normal function except that it has the variable b available to it because of the closure.
Looking at the hoisting example from this site, I don't get why the below alters 1 even after the hoisting:
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a); // alerts 1
is actually
var a = 1;
function b() {
function a() {}
a = 10;
return;
}
b();
alert(a);
Shouldn't it alter 10 because a is still assigned to 10 before b function returns? Why does calling an empty a function cause this? On a related note, why does the below not alert function but still alter 1? Doesn't a get reassigned to a function with the declaration?
var a = 1;
function a() {}
alert(a);
Let's take it line by line,
Here, b(); you call the function b. What has the function b in its body? The declaration of a new function whose name is a. When you access a inside the b, you actually don't access the global variable a, but the function you just declared. So the 10 will be set to the pointer that points to function called a and not the global variable called a
But why does the first block of code alerts 1? I am confused
Because when the JavaScript engine goes to execute the assignment:
a = 10;
checks where a has been defined. Since in the current scope, where you try to set 10 to a, there is a function declaration, whose name is a, Then will happen that I described above. But you would say why? The function declaration is below the assignment. The reason why this is happening is the fact the JavaScript engine first process the declarations in your script and then proceeds to the execution of your script. So when the engine would questioned about a, where a is defined, as always it will look first at the current scope. If there isn't there then it will look in the scope where the current scope is enclosed. In your case this is the global scope, as I can infer from your code. So if you hand't defined this function, the the second step I mentioned before would have been done and since there is variable called a, would had alter it's value. If there isn't there any variable then a would have been defined on the global scope and it's value would have been 10.
var a = 1;
function b() {
a = 10;
return;
// I renamed the function from a to c to notice the hoisting
function c() {}
}
b();
console.log(a);
there is such javascript code:
function a() {
a = 3;
return a;
}
console.log(a());
console.log(a());
After execution it prints out: 3, Type error. Could anybody explain why, please
You have a scope issue
Because you didn't use "var" you are overriding the global "a" variable (used to be your function) with a number (3).
When you try to execute it a second time, it's no longer a function but a number, which throws the type error.
function a() {
a = 3; // you just over-wrote a()
return a;
}
console.log(a()); // 3, but now "a" === number, not function
console.log(a()); // ERROR, you treated "a" as a function, but it's a number
what you want
function a() {
var a = 3; // using var makes "a" local, and does not override your global a()
return a;
}
console.log(a()); // 3
console.log(a()); // 3
Using var is recommended almost always inside a function, otherwise you're polluting, or worse overriding, global variables.
In JS, var enforces your variable into the local scope (your function).
Note that using var in the global scope still creates a global variable
If you were trying to set a as a variable, then var is needed in front. Because you didn't do so, it is exposed to the global scope, in which it is part of the window object, and you can access it with window.a. So, the best thing to do is to change the first body line of your function to say: var a = 3.
The value of 'a' seems to lose global scope when the constructor a is called.
var a = 6;
function b() {
a = 10;
function a() {}
console.log(a); //10
}
b();
console.log(a); //6
The order is interpreted as shown below due to variable hoisting. Note that as #ShadowCreeper correctly points out, function a(){} is actually creating a local variable a inside of function b which is hoisted as shown below.
var a;
var b;
a = 6;
b = function() {
var a;
a = function(){};
a = 10;
console.log(a); //10
}
b();
console.log(a); //6
Because you are creating a local variable (the function a) then replacing that local variable's value (the function) with 10.
One way to avoid things like this is to precede all local variables and functions with "_" (underscore).
This answer has a really nice explanation of what is going on here.
The summary is that Javascript is processed in two phases, compilation and then execution. The function definitions occur during the compilation step, so inside of b the compiler sees the definition function a() {} and the local variable a is created within the scope of b. Later on when the code is executed, the scope of b already contains the local variable a before any code is executed, so the line a = 10; is just giving the local variable a new value. The function definition was already processed during compilation so that will not happen during execution, so console.log(a) will output 10.
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
How is the output of 1 displayed for a? What does the
return;
function a() {}
within the function body perform?
You declare a symbol "a" in the function with its last line. That's the "a" affected by the assignment statement.
Function declaration statements are hoisted up to the top of the function and are interpreted first. Thus, the assignment statement effectively happens after you've declared a function (local to the "b" function) named "a". The assignment, therefore affects that symbol, not the global "a".
Remember that variables aren't typed, so the fact that you've bound a name to a function doesn't prevent it from being assigned a numeric value later.
You code is misleading and in a style that makes people think execution order matters. The standard JavaScript engine these days will take that and reformat prior to running it to:
var a = 1,
b = function() {
var a = function() {};
a = 10;
return;
};
b();
alert(a);
Now you can understand what is actually happening. "a" is declared again inside the function "b" so there is actually two "a" variables now. One is "window.a" and the other one is "b var a" but NOT "b.a" because its not accessible outside of the closure or function.
In other words, you get what you code for.
Please make your code readable and don't confuse the point.