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.
Related
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);
var change8 = function()
{
console.log(a);
console.log("End of function");
a = 10;
}
change8();
Return Reference Error
var change8 = function()
{
console.log(a);
console.log("End of function");
var a = 10;
}
change8();
Return Undefined
Why first code return Reference Error But Second code return undefined ?
Javascript does something called hoisting, in which before it executes, it looks for var declarations and creates those variables. Since you used var a in the second, it creates the variable, but it isn't defined when used. In the first one, a doesn't exist until you create it, so it's a reference error.
It is called variable hoisting. In JS declared variables are actually hoisted (moved up) to top of the scope they bound to, so in your case they are moved up to beginning of your function. In the second example a is treated as it is actually declared at the top of method before any of the assignments, then assigned to 10 later. So when you print a the variable is defined but its value is not assigned yet.
var change8 = function()
{
var a;
console.log(a);
console.log("End of function");
a = 10;
}
But in the first example a is not defined with var keyword so a will be treated as a global variable and won't be available until the assignment. Thus when it is called before the assignment the error will occur.
For understanding declaring variables with var keyword check the following answer
var change8 = function()
{
console.log(a);
console.log("End of function");
a = 10;
}
change8();
variable a is assigned undefined in the global context since JavaScript only hoists declarations, not initializations. Consider the same code as -
var a; // is = undefined
// in global context
var change8 = function()
{
console.log(a);
console.log("End of function");
a = 10;
}
change8();
Hence you'll get - Uncaught ReferenceError: a is not defined
This won't happen in 2nd code because you've explicitly declared your variable with var. Read more about hoisting here.
It is because,in the first snippet you are using 'a' before declaring it with var, thus 'a' belongs to the global scope, hence a reference error when you call your method because 'a' will only be in the global scope when the third line 'a = 10' was executed
In the second one 'a' is undefined because it is being used before it was declared using var, albeit it is still in the function's scope, when function is called during run-time, the first line 'console.log(a)' does not know 'a'
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
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
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();