JavaScript scope gets changed? Why does this happen? - javascript

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.

Related

Order of hoisting in Javascript detailed

Question #1.
I understand that "var" is function scoped, but does javascript order the hoist alphabetically? or first come first serve.
function x () {
var b;
var c;
var a;
}
After hoisting, does the result become this or the same result as above:
function x() {
var a;
var b;
var c;
}
Question #2.
I understand that function is hoisted before variables.
When I run this:
function x() {
var b = 2;
var c = 3;
var a = 1;
function y() {
var d = 4;
}
}
console.log(x);
I don't see the "function y()" being printed before the vars.
The order in which the variable names are "created" when hoisted doesn't matter, because just creating a variable name (possibly in addition to creating a function tied to the variable name, in the case of a function declaration) doesn't affect anything else. Nothing involved in it has any side effects, so the order in which the interpreter actually creates the variable names is opaque and irrelevant. That's a good thing - it means you don't have to worry about it.
That's assuming you're wondering about how things work at runtime, and don't have any syntax errors. If you do have syntax errors and are declaring variables with const or let, duplicate variable declarations for the same variable name in the same scope are forbidden, so the first duplicate identifier (in the same order as in the source code) will throw a syntax error.
let foo;
function foo() { // <-- This line throws
}
I don't see the "function y()" being printed before the vars.
When you do
console.log(x);
where x is a function, you'll just be given the function source code, which will be exactly as you typed it in the script - the code isn't altered in any way, so any "hoisting" effects won't be visible.

Hoisting in javascript along with global variable

The below code gives an output of undefined. I was of the impression that all variable and function declarations are hoisted to the top of their scope and so b should now be at the top the scope before calling a(). However, I still get undefined as my output?
a()
var b = 5;
function a() {
console.log(b)
}
You misunderstand how hoisting works. It doesn't hoist the assignment, it only hoists the declaration. Your code is equivalent to the following:
var b; // undefined
function a(){
console.log(b)
}
a();
b = 5;
Yes the variable declaration is hoisted, but the value is not set on b. The code looks like this
var b
function a(){
console.log(b)
}
a()
b = 5;
Hoisting means the variables will be created “at the top” - but it does not change anything about the time the value assignment happens, the b = 5 part still happens when execution reaches the part where it’s written. So if you call a() before that, b exists, but has not gotten any value assigned yet … hence, undefined
You are using a function declaration to create a function. So function declaration is also hoisted so they are being used before declaring.

How does an empty function declaration work with hoisting in javascript?

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);

Difference in declaring variable

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

Function Scopes Understanding Unclear

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.

Categories