Value of variable changes when page reloads - javascript

While coding for simple function declaration, there is a strange behavior by Firefox Scratchpad.
console.log(x);
var x = 0;
var func = function() {
console.log(y);
var y = 1;
};
func();
When I executed above code first time with Run, it gave result as below :
undefined undefined
But when I executed it second time, it gave below result :
0 undefined
So I assumed that the value must saved in cache, but then why wasn't the variable y still undefined?
Also when I repeated it with Reload and Run, the first result was repeated.

Its all about var top-hoisting. and function's block scope
When you run the first time your code actually look like this one.
var x;
console.log(x); // undefined as still x is not defined
x = 0;
var func = function() {
var y;
console.log(y); //undefined as still y is not defined
y = 1;
};
func();
Now,when you re-run second time,status of func() is not going to change as it redefined the block scope of func
So at second run
var func = function() {
var y;
console.log(y); //undefined as still y is not defined
//as scope is re-initializd
y = 1;
};
In javascript,every function when invoked, create a new execution context
but as var x; declared and defined in global scope during first time executiion,it is fetched from there. so, x=0 and y=undefined

Since first time when you execute that time there is no x and y variable declared before using it.
As soon as it comes to second line x is declared as global which remains in your page scripts. but in case of y variable, it is declared inside the function, its scope limited to function only hence y is not going to be global.
Hence when you refresh your page that time x variable gets that global value but not in case of y.
Its all about scope of variable in Javascript

Related

Global scope, variable outside function Javascript

I have declared var example at the beginning (it should be in global scope, or?!).
Why it is undefined after calling the function?
var example;
function test(){
var x = 2;
var y = 5;
var example = x + y;
console.log(example); // 7: works OK after calling the function
};
test();
console.log(example); // undefined ?!
Edit:
Hello, Thanks for your answers, I´ve found an article about this - Variable Shadowing
The reason is you have initialized the variable twice. First Initialization outside the function block which is globally available, Second within the function block which is specifically available to the function block.
Your Second Initialization will override the first within the function. After execution of the function, the second example variable will no longer be available and it will be referencing the globally declared first example variable.
var example;
function test(){
var x = 2;
var y = 5;
example = x + y;
console.log(example); //Prints the value
};
test();
console.log(example); // Prints the value
the first console.log(example) is running the example inside the function block, so it will print the value of the command you gave.
the second console.log(example) is running the example you declare in first line which is doesn't has value, so it will print undefined.

How to access a variable from outer scope in JavaScript

In the example bellow, I am trying to access the x that is in the function outer.
I was expecting to get 20 as an output, however the output is undefined.
Can someone explain why is that happening, and is there a way to access the outer x?
var x = 10;
function outer() {
var x = 20;
function inner() {
var x = 30;
function printX() {
console.log(outer.x);
}
printX();
}
inner();
}
outer();
Scopes aren't designed like that in JavaScript. In order to attach the variable x to its scope, you would need to reference the object for that scope either by name or by this reference.
What is happening in your example is that your call to printX attempts to log the variable x attached to the function outer. functions derive from objects in JavaScript, and as a result they may have properties attached to them, so instead of giving you a reference error, you get undefined instead, as the variable does not exist.
For more information on scoping, please see my answer on scope in JavaScript.
var x = 10; // Globally scoped variable named "x"
function outer() {
var x = 20; // Locally scoped to outer function variable named "x"
// in outer function, this variable takes precedence over the
// globally scoped x which was 10
function inner() {
var x = 30; // Locally scoped to inner function variable named "x"
// in inner function, this variable takes precedence over the
// parent scoped x which was 20
function printX() {
console.log(outer.x); // Tries to read "x" property of the outer function
// If this had been console.log(x) it would give 30 because it is scoped to the function inner's variable environment
}
printX();
}
inner();
}
outer();
As for what to do going forward, it really depends on what the end goal was. The simple way to fix this would be, as pointed out in comments here, to simply rename the variables. However, that still wouldn't fix the main issue of trying to access the variable by property name instead of by variable name. In order to access a variable by name, simply use its name (and differentiate the names if they share scope), as opposed to trying to access the property name which in this case doesn't exist.
Since it hasn't been mentioned here yet, I will add another possible way to do this by leveraging this and scope by calling the functions with .apply(), like so:
var x = 10;
function outer() {
var x = 20;
function inner() {
var x = 30;
function printX() {
// this now contains all 3 x variables without adding any parameters to any of the functions
console.log("Window x:", this.windowX);
console.log("Outer x:", this.outerX);
console.log("Inner x:", this.innerX);
}
// pass through existing context (which we got from inner.apply(...) down below, as well as add
// inner() x value to the new context we pass to printX()
printX.apply({...this, innerX: x});
}
// pass through existing context (which we got from outer.apply(...) down below, as well as add
// outer() x value to the new context we pass to inner()
inner.apply({...this, outerX: x});
}
// pass through window level x as "this" to outer(). Technically it's still available via window.x,
// but this will be consistent with the others
outer.apply({windowX: x});
You are not creating an object attribute but internal variables. Which you also shadow (that is that you define another with the same name in an inner scope) so that you cannot reach them.
Basically you can access outer.x but you have not set it (only a function scoped variable named x). And to answer your question "if you can get to that variable": No sorry. since you have shadowed it by defining an inner variable with the same name.
What you could do is this:
var x = 10;
function outer() {
outer.x = 20;
function inner() {
inner.x = 30;
function printX() {
console.log(outer.x);
}
printX();
}
inner();
}
outer();
but that would just make the other variables useless, and also setting variables on functions just because you can is not the best practice.
Keep learning.
You can take a look at the concept of scope to get more clarity, but the first x is in the global scope and can be accessed within the function, but you reassigned the variable value to be 20 within the outer function. If you console log the value of x within the outer function, but not inside the inner function, the result will be 20. You assigned the value 30 to x in the inner function, so when you access x within the inner function, it will be 30. If you console.log(x) in each location, you will see the different results.
var x = 10;
function outer() {
var x = 20;
function inner() {
var x = 30;
function printX() {
console.log(x);
}
printX();
}
inner();
console.log(x);
}
outer();
console.log(x);

Javascript: global Var definition not at beginning [duplicate]

I understand Hoisting of variables is done in Java Script. I am unable to get why it outputs as undefined
do_something()
{
var foo = 2;
console.log(foo);
} do_something() // it prints 2
do_something()
{
console.log(foo); var foo = 2;
} do_something() // it prints undefined
As javascript do hoisting the second function also should print 2 as per my understand.buy why doesn't it
This is how the interpreter sees your code,
do_something() {
var foo;
console.log(foo); // undefined
foo = 2;
}
do_something();
So it is printing undefined. This is a basic of variable hoisting. Your declarations will be moved to the top, and your assignation will remain in the same place. And the case is different when you use let over var.
Javascript only hoists declarations, not initializations.
var x = y, y = 'A';
console.log(x + y); // undefinedA
Here, x and y are declared before any code is executed, the assignments occur later. At the time "x = y" is evaluated, y exists so no ReferenceError is thrown and its value is 'undefined'. So, x is assigned the undefined value. Then, y is assigned a value of 'A'. Consequently, after the first line, x === undefined && y === 'A', hence the result.
Variable Declaration
Only the declaration is hoisted. the assigned variables are not hoisted. So you are
The second function outputs undefined because you set the variable after you called it. The code you wrote is synchronous which means its read by the interpreter line by line, executed in order. If you don't define the variable before calling it, the console outputs undefined.
This article explains it in more detail.
Only the declaration is hoisted, any assignment to a variable always stays where its originally from.

Javascript Hoisting : difference between calling x and window.x

Can anyone explain the hoisting behavior in the below scenarios?
alert(x);
var x = 10;
Result: alert-undefined
In the below case, x is not defined using 'var' keyword - hence attaches to the global scope.
alert(x);
x = 10; // not given a var
Result: error
In case if we replace x with window.x, we get alert as undefined!
alert(window.x); // calling the variable with window namespace
x = 10; // not given a var
Result: alert-undefined
Can you explain why it is different in calling a variable (which is attached to global scope) with the variable name (x) and with window namespace (window.x)?
The term "hoisting" is often misunderstood to mean that certain statements are moved to the top of their execution context, which is not what happens and why the term should be avoided.
What actually happens is that all declarations are processed first, so any variable declared with var (and any function created by a function declaration) exists before any code is executed. Then code execution begins.
So the variable x is created and assigned the value undefined before any code is executed (per ECMA-262), then later, during execution, it may be assigned some value.
So in the case of:
alert(x);
var x = 10;
x exists when alert is called, but has yet to be assigned a value other than undefined.
In:
alert(x);
x = 10;
x is not declared, so it does not exist when alert is called, hence the error. After the alert (if the code kept running), the assignment to x would create a property of the global (window in a browser) object named x and assign it a value of 10.
In:
alert(window.x);
x = 10;
It is a quirk of ECMAScript that global variables are also available as properties of the global object. The expression window.x attempts to read the x property of the window object. Since no such property exists, the return is undefined. Then the next statement creates x as a global variable and hence window.x now exists with a value of 10.
var x hoists the variable in the entire scope it's valid in, so the name x is available and valid anywhere within the scope. Its initial value is undefined, it only receives its value after the alert.
In case of a plain x, the variable is not hoisted because there's no var, so the bubbling up to window and its creation there only happens on the line x = 10, which is after the alert, which means the variable is entirely undefined and invalid at the time you try to alert it.
Any non-existing property of any object returns undefined, so testing window.x at a time when that property isn't set returns undefined as expected. That's how you do membership testing in Javascript: check whether a specific property equals undefined.
In the first case, var x gets hoisted, so x does exist when you call it (even though the value is undefined)
In the second case, when you say y = 10, you're essentially saying window.y = 10, so there's no hoisting at all, that's why it can't find the variable at all and gives you an error.
alert(x);
var x = 10;
will treated as
var x;
alert(x);
x = 10;
So at the time of alert x has the value undefined by default;
alert(x);
x = 10;
will be treated as
alert(x);
x = 10; // If this line runs in use strict mode then this line will throw error otherwise in non strict mode x will be added to global object ie. window
So will throw error because of x is undefined at the time of alert
alert(window.x);
x = 10;
will be treated as
alert(window.x);
x = 10;
alert will alert undefined because window is an object and it is having no property named as x at the time of alert so undefined
Later the line x = 10; will add the x to global object if in non strict mode, and will throw error if in strict mode

Could anyone please explain this behavior of function inside another function?

I was trying to understand lexical scoping in Javascript. In the below example, I have written a function inside an another function. When I run this, I would expect to pop-up "dad" in the first alert and "mom" in the second alert. But what actually happens is, it shows "undefined" in the first pop-up and "mom" in the second.
function first(){
var x = "dad";
function second(){
alert(x);
var x = "mom";
alert(x);
}
second();
}
first();
Can someone please explain why variable "x" defined in parent function is not visible in the child function? Strangely, when I remove the declaration for variable "x" inside the child function, it works fine. Could someone give insight of the lexical scoping scenario valid here?
The var x in 'second' declares a variable 'x', which hides the variable 'x' in the outer function. Any reference to 'x' in 'second' function refers to that variable, even if it's before the declaration. The value of the variable before the declaration will be 'undefined'.
You can look up 'hoisting' for more information. See: http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
You re-declared x in second by using a var statement after the alert. This makes it a different x than the one declared in first.
Furthermore, JavaScript uses a technique called hoisting. When a variable is declared in a scope, that declaration is moved to the top of the scope during a pre-execution pass. If declaration and assignment are being done in one statement, the declaration is broken away from the assigment. Declaration is moved to the top of the scope, causing an undefined variable, while assigment is left where it origianally was.
The resulting code after the pre-pass is something like below (I've only showed hoisting of variables here and left functions alone)
function first(){
var x;
x = "dad";
function second(){
var x; //new variable in local scope, declared not defined
alert(x); //alerts undefined
x = "mom"; //defines local `x` as "mom"
alert(x); //alerts "mom"
}
second();
}
first();
Thus, in the first alert your x is new and undefined, and in the second it is defined. Meanwhile, the value of x in first has remained unchanged.
In order to get what you were expecting, and to keep the same x in both functions, you would remove the var declaration from second and leave the assignment:
function first(){
var x = "dad";
function second(){
alert(x);
x = "mom";
alert(x);
}
second();
}
first();

Categories