IIFE and Global scope in javascript - javascript

Why does the following code result in logging of b while a is still undefined?
(function(){ var a=b=5; })();
console.log('b:'+b);
console.log('a:'+a);

Because var a=b=5; statement defines only local a variable and in fact is interpreted like
var a = (b=5);
which equals to
b = 5;
var a = 5;
which assigns 5 to a global b variable and defines a local a variable.
The proper way to define 2 local variables without value repetition would be
var b = 5, a = b;

In JavaScript if you ommit the var keyword before a variable, it will be considered as global.
So here b is a global variable and a is only a local to that function's scope.
That's why you are getting the error while accessing the a.

Never mind, I figured it out myself as it wouldn't let me sleep.
There are 2 assignments happening within the IIFE whereas only 1 declaration.
The statement var a=b=5; declares the variable a with var but simply does assignment for the other variable b.
b is actually never declared here, just assigned - making it a global variable.
Hence b is accessible to the log statement outside the function, which prints its value as 5.
In other words, under 'strict' mode, the code will look like this:
(function() {
'use strict';
var a = window.b = 5;
})();
console.log(b);

A variable can be defined in 2 ways:
var a= 5 // first
a=5 // Second
In first way, a is a local variable, but in second way, it becomes a global variable.
So, when you do var a=b=5, b is a global variable and hence retains value.

Related

variables from IIFE accessible in global scope

how come the output of this IIFE is 5?
(function() {
var a = b = 5;
})();
console.log(b);
I tried console.log(a) but it gives a reference error as expected
how come 'b' is alive in global scope?
Interesting question. Though it is not related to IIFE's or hoisting at all. Notice how "a" is not defined!
Your code sample
function test() {
var a = b = 5;
}
is semantically equivalent to this:
function test() {
var a = 5;
// this is essentially the same as `window.b = a`
b = a;
}
since you did not declare "a" (aka var a;) it ends up in the global scope.
In strict mode this would not work.
This is happening simply because you're declaring b as a global variable, not a local one.
(function() {
var a = b = 5;
})();
It may look like it's being defined locally because of var, but that applies to a only.
That's because of "leaking", which means to unintentionally make locally declared variables available to the global scope. More informations about can be found here. Let's split your code:
var a = b = 5;
This means: a takes the value of b, which is 5. The variable b is implicitly declared and initialised in this case (with b = 5), and since you're not specifying its block scope (that's because var is referring to a, not b) it's bounded to the global scope.
From documentation.
The scope of a variable declared with var is its current execution context and closures thereof, which is either the enclosing function and functions declared within it

variable value at top and then changing value in function showing undefined why? [duplicate]

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 5 years ago.
if i declare variable at top with some value, then using that variable is showing undefined why?
var a = 100;
function test(){
console.log(a);
var a = 1000;
console.log(a);
}
test();
The output is undefined and 1000 why?
In your function, the local variable masks the global one.
var a = 100;
function test(){
console.log(a);
var a = 1000;
console.log(a);
}
test();
The fact that your var statement is in the function as well as global scope doesn't change anything. The global variable is masked for the whole function.
So, for the whole execution of the function, the global variable will reference the local one, and not the global one.
Outside of that function, though, the global variable will still exist
If you want to access the variable inside the function you can use
console.log(window.a);
It's because of the way JavaScript compiles the code.
Firsr it looks for declarations in the scope, then, if inner scopes are present, it looks for their own scope, in this case I'm pretty sure it's like the following:
Global scope will have a variable named a and a value of 100 assigned to it
There is a global function declaration named test, it needs its own scope, let's go for it
2.1. This scope will have a variable named a (uninitialized)
2.2 There is a call for the console object's function named log, it needs to have the variable named a, is that variable in this scope? Well, it looks like it is, but does not have a value assigned now so it is undefined.
2.3 NOW I have something to assign the variable, it's 1000, ok, let's continue.
2.4 There is a call for the console object's function named log, it needs to have the variable named a, is that variable in this scope? Well, it looks like it is, AND its value is 1000 console.log(a) => 1000
There is a call for the test function see 2.1
So, when you call the first console.log(a) the engine knows there is a local scope's variable named a, but it is not yet initialized, that's why you get undefined, then, in the second call, the local scope's a variable has a value of 1000 assigned to it, local scope is higher in hierarchy than parent scope so the value for the log will be 1000.
You might want to read about Hoisting of a javascript variable.
Because of hoisting, var a = 1000; is treated as var a; and a = 1000; as two different statements. The var a; statement, which is variable declaration, is moved to the top inside the function due to hoisting.
Now your function is as good as
var a = 100;
function test(){
var a;
console.log(a);
a = 1000;
console.log(a);
}
test();
var a; statement declares a local variable but is still undefined. So you get undefined on first console.log(a);.
To access the global variable learn how to use this like this.a.

Variable Scope and Var

It all started with these simple lines of code:
a = 3;
b = 2;
function line(x) {
var a = 5;
var b = 4;
return a*x+b;
}
// returns 17
b = line(a) - b;
alert(b);
// returns 36
c = line(a) + b;
alert(c);
Both alerts return 17 and 36, respectively.
The control works as expected. Until…
I make the mistake of changing
the inside of the function like so:
function line(x) {
var a = 5;
b = 4;
return a*x+b;
}
Suddenly line 13 returns 15, line 17 returns 23
and the situation continues to deteriorate as I follow var
down the rabbit hole, becoming more enmeshed as I make my descent.
I realize I could make a mental note to always use var
and rest knowing my code will always work as intended
but this has become a matter of principle now and now I need
to understand how var actually works.
Here are links to the four hells,
made by (and possibly for) me:
Riddle #1
http://jsfiddle.net/js_test/gNEmY/
Riddle #2
http://jsfiddle.net/js_test/FJVYL/
Riddle #3
http://jsfiddle.net/js_test/Vz7Sd/
Riddle #4
http://jsfiddle.net/js_test/RaA5J/
If anyone could give me insight
into what's happening under the hood
to wit, what happens during each alert() call;
I would really appreciate it.
var creates a local variable, scoped to the function in which it appears. Any variable that is declared in the global scope becomes a property of the global object (in a browser, window), and any variable referenced in a function which is not declared with var in that function refers to the surrounding scope, quite possibly the global scope.
There is also a new keyword, let, which is coming in the upcoming version of ECMAScript and is already in some browsers, which creates a block-scoped variable.
So, in your first example (I am going to assume this is running in a browser), you create window.a and window.b which are bound to 3 and 2, respectively. Function line declares local variables a and b. When window.a is passed to line, the parameter x is bound to the value 3 (the value of window.a). Local variables a and b are 5 and 4, respectively. These have nothing to do with window.a and window.b. The calculation a*x+b is, thus, 5*3+4, or 19.
The code b = line(a) - b passes window.a to line, calculates the value 19, subtracts the current value of window.b from it (2), resulting in 17, which is then assigned to window.b. The value of 36 comes from line(3) (which is still 19) plus 17 (the new value of window.b).
When you removed the var from the assignment to b in function line, you changed it so that b is no longer a local variable. In that case, all references to b in the function refer to the global value window.b.
In the case of your Riddle #2, where you got 23, after the first call window.b is equal to 15. When line(a) is called a second time, window.b is set back to 4, the a*x+b calculation still gets 19, and then window.b (4) is added again, making 23.
It is important to note that the var keyword declares a variable that is function-scoped, not block-scoped as you might expect from other C-derived languages. For example, in this function:
function scope(array) {
var a = 7;
for (var b = 0; b < array.length; ++b) {
var c = array[b];
}
alert(a + b + c);
}
All the variables have scope which extends over the entire function. In particular, the scope of c is not limited to the for loop.
A variable that is not declared in a particular scope doesn't necessarily reference a global variable, however. If it is nested inside another function scope, it will refer to that nested scope. Consider the following example:
var b = 7;
function outer() {
var b = 42;
function inner() {
return b; // refers to b in outer, not global
}
return inner();
}
alert(outer()); // 42, not 7
The variable declared without var is global variable, this is the rule.
But remember if you want to declare multiple local variable with one var, separate them with comma.
var a = 5; // local variable
b = 4; // global varialbe
var a = 5, // local variable
b = 4; // local varialbe
VAR declares a new instance in memory for a new variable. Simply saying b = 4 will try to change the value of b to 4. If b has not been initialized nothing will happen.
This ties into the concept of PRIVATE and LOCAL variables, and naming conventions.
Firstly, you have 2 variables called a and 2 called b. This is bad practice because you might change the value of the other one by mistake, or its old value could still be sitting in memory because it was already initialized and given a value. Remember, you do not always NEED to assign a value when initializing, it's just best practice.
Secondly, your function can modify a variable from the level above it. In other words, by taking away VAR on that one line it's possible to modify the original value of b which you set to 2 at the beginning of the file.
TLDR;
Don't use the same variable name more than once, and always use your VAR when trying to make a NEW variable.
If you're in the global scope then there's no difference.
If you're in a function then "var" will create a local variable, "no var" will look up the scope chain until it finds the variable or hits the global scope (at which point it will create it).
Source
In the case of your first function, line(a) is processed first, and by the time it runs, you've set b = 4. Therefore, and because b is a globally defined variable, when it runs line(a) - b, you're getting:
line(a) (returns 19)
And minus b (b = 4)
19 - 4 = 15
You can simplify your statement and get the same result:
//define global variable b
var b = 2;
function line(x) {
//x = 3
//update global variable b; it now = 4
b = 4;
//forget the math and just return 19
return 19;
}
//run function; before, b = 2, after b = 4
b = line(3) - b;
alert(b);
Likewise with your second example, because your function changes the value of global variable b, the only difference is that you're adding 4 instead of subtracting (19 + 4 = 23).
To avoid this confusing nature of variables, always be careful to differentiate between global and local variables whenever possible, and only drop var when you need to explicitly update global variables in functions. In actual fact too, since global variable always remain in memory, you should use globals only when you explicitly need them. Here's an unambiguous example:
var globalVar;
function someFunc(x) {
var tempVar = 4;
return x * tempVar;
}

JavaScript scope gets changed? Why does this happen?

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.

Initializing a JavaScript variable in the local scope

I'm studying variable scope in Javascript, and have come across the difference between variable declaration, and variable initialization. From talking to a developer I know, my understanding is that writing var before a variable declaration assigns the variable to the local scope, while not writing var before declaring the variable assigns the variable to the global scope. Is this true?
If writing var before declaring a variable does assign the variable to the local scope, is it necessary to write var later, when initializing the variable to keep it in the local scope? For example:
var someVariable;
// Do some things with JavaScript
someVariable = 'Some Value'
Since I declared someVariable in the local scope with var, but then initialized someVariable without using var, does JavaScript think that I just initialized one variable in the local scope, or that I declared one variable in the local scope, and then declared and initialized another variable in the global scope?
Later on, when I want to change the value of someVariable again, do I need to write var before the variable expression, or will JavaScript know that I'm changing the value of an already declared local variable? Technically speaking, how does JavaScript know when I'm changing the value of an already declared local variable, and when I'm declaring and initializing a global variable?
var something = "Initial value."
This means: "create a variable in the local scope and give it an initial value". The local scope means the function in which you use this statement.
something = "New value."
This means: "find variable 'something' in the nearest scope, and assign it a new value".
If you use the second statement without ever using the first, the statement will look for any definition of something in progressively bigger scopes (the function that contains your function, if it exists, the function that contains that, etc., until it reaches the global scope). If it finds something, it will assign to an already existing variable. If it finds nothing, it will create a global variable with that name.
If you use var first, you simply ensure that this search always stops at local scope.
These are the same:
var x;
// ...
x = 1;
...and...
var x = 1;
Both define a variable in the local scope and assign a value to it. If you want to change the value of the variable later in the same scope you can simply reference it by name:
x = 2;
If you're in a different scope however, unless the variable was declared in the global scope in the first place you will not be able to access it (it's "out of scope"). Attempting to do so will define a variable with that name in the global scope.
function a(){
var x = 1;
}
function b(){
x = 2; // 'x' in a is out of scope, doing this declares a new 'x' in global scope
}
a();
b();
When referencing a variable in the same scope it was declared, you do not need to prefix it with var, though you can:
var x = 1;
// ...
var x = 2;
...there's no need to do that. While it assigns 2 to 'x', it logically has no effect since var is already in local scope. If x had been declared globally however:
var x = 1;
function a(){
var x = 2;
console.log(x);
}
a();
console.log(x);
This will print first '2' and then '1'. By referencing x preceded with var in the function, it applies the local scope to the variable. Once the function completes the variable's original scope is restored (or the re-scope is lost, if you want to look at it that way). Thanks to #zzzzBov for pointing this out.
Hope this helps.
my understanding is that writing var before a variable declaration assigns the variable to the local scope, while not writing var before declaring the variable assigns the variable to the global scope. Is this true?
Not entirely.
function foo() {
var a = 1;
function bar() {
a = 2; // Still in the scope of foo, not a global
}
}
Since I declared someVariable in the local scope with var, but then initialized someVariable without using var, does JavaScript think that I just initialized one variable in the local scope, or that I declared one variable in the local scope, and then declared and initialized another variable in the global scope?
There is only one someVariable in that example.
Later on, when I want to change the value of someVariable again, do I need to write var before the variable expression
var scopes a variable for the entire function, no matter where in the function it appears.
If you define a variable using var, you can refer to the same variable without using the var keyword over and over. These refer to the same variable:
var someVariable;
//...code...
someVariable = 'rawr';
If you did use the var keyword every time you were changing the variable, you wouldn't get separate variables. The newest declaration would just overwrite the oldest declaration. So there's no point in using the var keyword except for initialization. To change the value of someVariable, you can just make assignments to the variable name like in the above example.
Basically, using var will create a new variable if there is no variable in that scope with the same name.
Now take this code for example:
var someVariable = 'initialized';
function test1(){
//this someVariable will be a new variable since we have the var keyword and its in a different scope
var someVariable = 'test1';
console.log(someVariable);
}
function test2(){
//because there is no var keyword this refers to the someVariable in the parent scope
someVariable = 'test2';
console.log(someVariable);
}
console.log(someVariable); //initialized
test1(); //test1
console.log(someVariable); //initialized
test2(); //test2
console.log(someVariable); //test2
With this example you can see that depending on what you want the code to do, you could be having problems. If you wanted test2 to act like test1 and forgot to use the var keyword you would be confused when you were expecting someVariable to be initialized and instead it was test2.
But you could have also purposely not used the var keyword because you wanted test2 to update the parent variable. So it is important that you use the var keyword correctly.
Not using var when initializing variables will create the variable on the global scope. This is not good practice. If you want variables on the global scope, manually put them there. i.e. window.someVariable = 'initialize'; That way anyone else that sees your code knows that you made it a global variable on purpose.

Categories