Related
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.
Today, I got completely surprised when I saw that a global variable has undefined value in a certain case.
Example:
var value = 10;
function test() {
//A
console.log(value);
var value = 20;
//B
console.log(value);
}
test();
Gives output as
undefined
20
Here, why is the JavaScript engine considering global value as undefined? I know that JavaScript is an interpreted language. How is it able to consider variables in the function?
Is that a pitfall from the JavaScript engine?
This phenomenon is known as: JavaScript Variable Hoisting.
At no point are you accessing the global variable in your function; you're only ever accessing the local value variable.
Your code is equivalent to the following:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
Still surprised you're getting undefined?
Explanation:
This is something that every JavaScript programmer bumps into sooner or later. Simply put, whatever variables you declare are always hoisted to the top of your local closure. So, even though you declared your variable after the first console.log call, it's still considered as if you had declared it before that.
However, only the declaration part is being hoisted; the assignment, on the other hand, is not.
So, when you first called console.log(value), you were referencing your locally declared variable, which has got nothing assigned to it yet; hence undefined.
Here's another example:
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
What do you think this will alert? No, don't just read on, think about it. What's the value of test?
If you said anything other than start, you were wrong. The above code is equivalent to this:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
so that the global variable is never affected.
As you can see, no matter where you put your variable declaration, it is always hoisted to the top of your local closure.
Side note:
This also applies to functions.
Consider this piece of code:
test("Won't work!");
test = function(text) { alert(text); }
which will give you a reference error:
Uncaught ReferenceError: test is not defined
This throws off a lot of developers, since this piece of code works fine:
test("Works!");
function test(text) { alert(text); }
The reason for this, as stated, is because the assignment part is not hoisted. So in the first example, when test("Won't work!") was run, the test variable has already been declared, but has yet to have the function assigned to it.
In the second example, we're not using variable assignment. Rather, we're using proper function declaration syntax, which does get the function completely hoisted.
Ben Cherry has written an excellent article on this, appropriately titled JavaScript Scoping and Hoisting.
Read it. It'll give you the whole picture in full detail.
I was somewhat disappointed that the problem here is explained, but no one proposed a solution. If you want to access a global variable in function scope without the function making an undefined local var first, reference the var as window.varName
Variables in JavaScript always have function-wide scope. Even if they were defined in the middle of the function, they are visible before. Similar phenomena may be observed with function hoisting.
That being said, the first console.log(value) sees the value variable (the inner one which shadows the outer value), but it has not yet been initialized. You can think of it as if all variable declarations were implicitly moved to the beginning of the function (not inner-most code block), while the definitions are left on the same place.
See also
Javascript function scoping and hoisting
Javascript variable declarations at the head of a function
There is a global variable value, but when control enters the test function, another value variable is declared, which shadows the global one. Since variable declarations (but not assignments) in JavaScript are hoisted to the top of scope in which they are declared:
//value == undefined (global)
var value = 10;
//value == 10 (global)
function test() {
//value == undefined (local)
var value = 20;
//value == 20 (local)
}
//value == 10 (global)
Note that the same is true of function declarations, which means you can call a function before it appears to be defined in your code:
test(); //Call the function before it appears in the source
function test() {
//Do stuff
}
It's also worth noting that when you combine the two into a function expression, the variable will be undefined until the assignment takes place, so you can't call the function until that happens:
var test = function() {
//Do stuff
};
test(); //Have to call the function after the assignment
The simplest way to keep access to outer variables (not just of global scope) is, of course, to try to not re-declare them under the same name in functions; just do not use var there. The use of proper descriptive naming rules is advised. With those, it will be hard to end up with variables named like value (this aspect is not necessarily related to the example in the question as this variable name might have been given for simplicity).
If the function might be reused elsewhere and hence there is no guarantee that the outer variable actually defined in that new context, Eval function can be used. It is slow in this operation so it is not recommended for performance-demanding functions:
if (typeof variable === "undefined")
{
eval("var variable = 'Some value';");
}
If the outer scope variable you want access to is defined in a named function, then it might be attached to the function itself in the first place and then accessed from anywhere in the code -- be it from deeply nested functions or event handlers outside of everything else. Notice that accessing properties is way slower and would require you to change the way you program, so it is not recommended unless it is really necessary: Variables as properties of functions (JSFiddle):
// (the wrapper-binder is only necessary for using variables-properties
// via "this"instead of the function's name)
var functionAsImplicitObjectBody = function()
{
function someNestedFunction()
{
var redefinableVariable = "redefinableVariable's value from someNestedFunction";
console.log('--> functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
console.log('--> redefinableVariable: ', redefinableVariable);
}
var redefinableVariable = "redefinableVariable's value from someFunctionBody";
console.log('this.variableAsProperty: ', this.variableAsProperty);
console.log('functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
console.log('redefinableVariable: ', redefinableVariable);
someNestedFunction();
},
functionAsImplicitObject = functionAsImplicitObjectBody.bind(functionAsImplicitObjectBody);
functionAsImplicitObjectBody.variableAsProperty = "variableAsProperty's value, set at time stamp: " + (new Date()).getTime();
functionAsImplicitObject();
// (spread-like operator "..." provides passing of any number of arguments to
// the target internal "func" function in as many steps as necessary)
var functionAsExplicitObject = function(...arguments)
{
var functionAsExplicitObjectBody = {
variableAsProperty: "variableAsProperty's value",
func: function(argument1, argument2)
{
function someNestedFunction()
{
console.log('--> functionAsExplicitObjectBody.variableAsProperty: ',
functionAsExplicitObjectBody.variableAsProperty);
}
console.log("argument1: ", argument1);
console.log("argument2: ", argument2);
console.log("this.variableAsProperty: ", this.variableAsProperty);
someNestedFunction();
}
};
return functionAsExplicitObjectBody.func(...arguments);
};
functionAsExplicitObject("argument1's value", "argument2's value");
I was running into the same problem even with global variables. My problem, I discovered, was global variable do Not persist between html files.
<script>
window.myVar = 'foo';
window.myVarTwo = 'bar';
</script>
<object type="text/html" data="/myDataSource.html"></object>
I tried to reference myVar and myVarTwo in the loaded HTML file, but received the undefined error.
Long story/day short, I discovered I could reference the variables using:
<!DOCTYPE html>
<html lang="en">
<!! other stuff here !!>
<script>
var myHTMLVar = this.parent.myVar
/* other stuff here */
</script>
</html>
Today, I got completely surprised when I saw that a global variable has undefined value in a certain case.
Example:
var value = 10;
function test() {
//A
console.log(value);
var value = 20;
//B
console.log(value);
}
test();
Gives output as
undefined
20
Here, why is the JavaScript engine considering global value as undefined? I know that JavaScript is an interpreted language. How is it able to consider variables in the function?
Is that a pitfall from the JavaScript engine?
This phenomenon is known as: JavaScript Variable Hoisting.
At no point are you accessing the global variable in your function; you're only ever accessing the local value variable.
Your code is equivalent to the following:
var value = 10;
function test() {
var value;
console.log(value);
value = 20;
console.log(value);
}
test();
Still surprised you're getting undefined?
Explanation:
This is something that every JavaScript programmer bumps into sooner or later. Simply put, whatever variables you declare are always hoisted to the top of your local closure. So, even though you declared your variable after the first console.log call, it's still considered as if you had declared it before that.
However, only the declaration part is being hoisted; the assignment, on the other hand, is not.
So, when you first called console.log(value), you were referencing your locally declared variable, which has got nothing assigned to it yet; hence undefined.
Here's another example:
var test = 'start';
function end() {
test = 'end';
var test = 'local';
}
end();
alert(test);
What do you think this will alert? No, don't just read on, think about it. What's the value of test?
If you said anything other than start, you were wrong. The above code is equivalent to this:
var test = 'start';
function end() {
var test;
test = 'end';
test = 'local';
}
end();
alert(test);
so that the global variable is never affected.
As you can see, no matter where you put your variable declaration, it is always hoisted to the top of your local closure.
Side note:
This also applies to functions.
Consider this piece of code:
test("Won't work!");
test = function(text) { alert(text); }
which will give you a reference error:
Uncaught ReferenceError: test is not defined
This throws off a lot of developers, since this piece of code works fine:
test("Works!");
function test(text) { alert(text); }
The reason for this, as stated, is because the assignment part is not hoisted. So in the first example, when test("Won't work!") was run, the test variable has already been declared, but has yet to have the function assigned to it.
In the second example, we're not using variable assignment. Rather, we're using proper function declaration syntax, which does get the function completely hoisted.
Ben Cherry has written an excellent article on this, appropriately titled JavaScript Scoping and Hoisting.
Read it. It'll give you the whole picture in full detail.
I was somewhat disappointed that the problem here is explained, but no one proposed a solution. If you want to access a global variable in function scope without the function making an undefined local var first, reference the var as window.varName
Variables in JavaScript always have function-wide scope. Even if they were defined in the middle of the function, they are visible before. Similar phenomena may be observed with function hoisting.
That being said, the first console.log(value) sees the value variable (the inner one which shadows the outer value), but it has not yet been initialized. You can think of it as if all variable declarations were implicitly moved to the beginning of the function (not inner-most code block), while the definitions are left on the same place.
See also
Javascript function scoping and hoisting
Javascript variable declarations at the head of a function
There is a global variable value, but when control enters the test function, another value variable is declared, which shadows the global one. Since variable declarations (but not assignments) in JavaScript are hoisted to the top of scope in which they are declared:
//value == undefined (global)
var value = 10;
//value == 10 (global)
function test() {
//value == undefined (local)
var value = 20;
//value == 20 (local)
}
//value == 10 (global)
Note that the same is true of function declarations, which means you can call a function before it appears to be defined in your code:
test(); //Call the function before it appears in the source
function test() {
//Do stuff
}
It's also worth noting that when you combine the two into a function expression, the variable will be undefined until the assignment takes place, so you can't call the function until that happens:
var test = function() {
//Do stuff
};
test(); //Have to call the function after the assignment
The simplest way to keep access to outer variables (not just of global scope) is, of course, to try to not re-declare them under the same name in functions; just do not use var there. The use of proper descriptive naming rules is advised. With those, it will be hard to end up with variables named like value (this aspect is not necessarily related to the example in the question as this variable name might have been given for simplicity).
If the function might be reused elsewhere and hence there is no guarantee that the outer variable actually defined in that new context, Eval function can be used. It is slow in this operation so it is not recommended for performance-demanding functions:
if (typeof variable === "undefined")
{
eval("var variable = 'Some value';");
}
If the outer scope variable you want access to is defined in a named function, then it might be attached to the function itself in the first place and then accessed from anywhere in the code -- be it from deeply nested functions or event handlers outside of everything else. Notice that accessing properties is way slower and would require you to change the way you program, so it is not recommended unless it is really necessary: Variables as properties of functions (JSFiddle):
// (the wrapper-binder is only necessary for using variables-properties
// via "this"instead of the function's name)
var functionAsImplicitObjectBody = function()
{
function someNestedFunction()
{
var redefinableVariable = "redefinableVariable's value from someNestedFunction";
console.log('--> functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
console.log('--> redefinableVariable: ', redefinableVariable);
}
var redefinableVariable = "redefinableVariable's value from someFunctionBody";
console.log('this.variableAsProperty: ', this.variableAsProperty);
console.log('functionAsImplicitObjectBody.variableAsProperty: ', functionAsImplicitObjectBody.variableAsProperty);
console.log('redefinableVariable: ', redefinableVariable);
someNestedFunction();
},
functionAsImplicitObject = functionAsImplicitObjectBody.bind(functionAsImplicitObjectBody);
functionAsImplicitObjectBody.variableAsProperty = "variableAsProperty's value, set at time stamp: " + (new Date()).getTime();
functionAsImplicitObject();
// (spread-like operator "..." provides passing of any number of arguments to
// the target internal "func" function in as many steps as necessary)
var functionAsExplicitObject = function(...arguments)
{
var functionAsExplicitObjectBody = {
variableAsProperty: "variableAsProperty's value",
func: function(argument1, argument2)
{
function someNestedFunction()
{
console.log('--> functionAsExplicitObjectBody.variableAsProperty: ',
functionAsExplicitObjectBody.variableAsProperty);
}
console.log("argument1: ", argument1);
console.log("argument2: ", argument2);
console.log("this.variableAsProperty: ", this.variableAsProperty);
someNestedFunction();
}
};
return functionAsExplicitObjectBody.func(...arguments);
};
functionAsExplicitObject("argument1's value", "argument2's value");
I was running into the same problem even with global variables. My problem, I discovered, was global variable do Not persist between html files.
<script>
window.myVar = 'foo';
window.myVarTwo = 'bar';
</script>
<object type="text/html" data="/myDataSource.html"></object>
I tried to reference myVar and myVarTwo in the loaded HTML file, but received the undefined error.
Long story/day short, I discovered I could reference the variables using:
<!DOCTYPE html>
<html lang="en">
<!! other stuff here !!>
<script>
var myHTMLVar = this.parent.myVar
/* other stuff here */
</script>
</html>
I am new to JavaScript.
<html>
<body>
<script type="text/javascript">
var x=5;
document.write(x);
document.write("<br />");
var x;
document.write(x);
</script>
</body>
</html>
Result is:
5
5
When x is declared the second time it should be undefined, but it keeps the previous value. Please explain whether this redeclaration has any special purpose.
You aren't really re-declaring the variable.
The variable statement in JavaScript, is subject to hoisting, that means that they are evaluated at parse-time and later in runtime the assignments are made.
Your code at the end of the parse phase, before the execution looks something like this:
var x;
x = 5;
document.write(x);
document.write("<br />");
document.write(x);
var alone does not perform an assignment. It only flags that when you use the variable name throughout the scope in which the var occurs, you are talking about a local variable and not global (the controversial default). The var is spotted when the function is parsed and holds throughout that scope, so where you put it is irrelevant:
var a= 0;
function foo() {
a= 1;
return a;
var a;
}
var b= foo();
alert('global a='+a+', local a='+b);
Results in global a= 0, local a= 1: even though the var statement is never reached in the course of execution of foo(), it is still effective in making a a local variable.
So declaring var x a second time in the same scope is completely redundant. However you might sometimes still do it, typically when you re-use a local variable name for a second independent use within the same function. Most commonly:
for (var i= 0; i<onething.length; i++) {
...do some trivial loop...
}
for (var i= 0; i<anotherthing.length; i++) {
...do another trivial loop...
}
Whilst you could certainly omit the second var, and tools like jslint would demand you do so, it might not actually be a good idea.
Imagine you later change or remove the first loop so that it no longer declares i to be var. Now the remaining second loop suddenly changes meaning from a local to a global variable. If you fail to notice when updating the first loop that the second loop has a hidden dependency on it (and you might very well fail to notice that given how the eyes elide the pattern for(...=0 ; ...<...; ...++) into “oh, that's just a standard iterator”), you've got a subtle and annoying-to-debug problem.
so when the second time when its declared x should be undefined
What part of the specification says this?
"Undefined behaviour" does not mean "the variable will be undefined".
As far as my understanding of javascript goes, the use of the var keyword is completely optional in the global scope. It's a different story for functions.
When inside a function, use the var keyword to indicate that the variable is local to the function (as opposed to being global by default).
I personally use var in the global scope to show that a variable is being declared and/or utilized for the first time.
You can reference http://www.w3schools.com/js/js_variables.asp for more info.
That second var x is totally superfluous.
Within the same scope, it is totally unnecessary to "redeclare" a variable.
Also, a programmer might want to use var to localize a variable:
<script>
var x= 'this is global x';
function my_x() {
var x= 'localized x';
alert(x);
}
my_x();
alert(x);
</script>
You should never redeclare a variable within the same scope, if you really want to change this then assign to it. Redeclaration is not required to create a different object in this dynamic language, if you want x to be a string just assign:
x = "hello";
It is not required that you set it back to undefined or redeclare first.
Please note that changing the variable type is not very good practice in most situations, simply stating that it is a possibility if that's what you require.
I recently wrote code like:
var obj1 = get_an_object();
var v = obj1.get_velocity();
v += changes_in_velocity();
obj1.set_velocity(v);
var obj2 = get_an_object();
var v = obj2.get_velocity();
v += changes_in_velocity();
obj2.set_velocity(v);
(The actual code was more complicated and less repetitive)
So far as the browser is concerned, the second var v statement was redundant and pointless. To me, it served two purposes. It said to forget everything I knew about the old v, because this was a new usage. And it meant I could re-order the code, or comment out the first half, without breaking things.
Or more specific to what I need:
If I call a function from within another function, is it going to pull the variable from within the calling function, or from the level above? Ex:
myVar=0;
function runMe(){
myVar = 10;
callMe();
}
function callMe(){
addMe = myVar+10;
}
What does myVar end up being if callMe() is called through runMe()?
Jeff is right. Note that this is not actually a good test of static scoping (which JS does have). A better one would be:
myVar=0;
function runMe(){
var myVar = 10;
callMe();
}
function callMe(){
addMe = myVar+10;
}
runMe();
alert(addMe);
alert(myVar);
In a statically scoped language (like JS), that alerts 10, and 0. The var myVar (local variable) in runMe shadows the global myVar in that function. However, it has no effect in callMe, so callMe uses the global myVar which is still at 0.
In a dynamically scoped language (unlike JS), callMe would inherit scope from runMe, so addMe would become 20. Note that myVar would still be 0 at the alert, because the alert does not inherit scope from either function.
if your next line is callMe();, then addMe will be 10, and myVar will be 0.
if your next line is runMe();, then addMe will be 20, and myVar will be 10.
Forgive me for asking - what does this have to do with static/dynamic binding? Isn't myVar simply a global variable, and won't the procedural code (unwrap everything onto the call stack) determine the values?
Variables are statically scoped in JavaScript (dynamic scoping is really a pretty messy business: you can read more about it on Wikipedia).
In your case though, you're using a global variable, so all functions will access that same variable. Matthew Flaschen's reply shows how you can change it so the second myVar is actually a different variable.
This Page explains how to declare global vs. local variables in JavaScript, in case you're not too familiar with it. It's different from the way most scripting languages do it. (In summary: the "var" keyword makes a variable local if declared inside a function, otherwise the variable is global.)
Unless you use the keyword var to define your variables, everything ends up being a property on the window object. So your code would be equivalent to the following:
window.myVar=0;
function runMe(){
window.myVar = 10;
window.callMe();
}
function callMe(){
window.addMe = window.myVar+10;
}
If you keep this in mind, it should always be clear what is happening.
I would like to add that lambda expressions are also statically scoped at the location that the expression is defined. For example,
var myVar = 0;
function foo() {
var myVar = 10;
return { bar: function() { addMe = myVar + 10; }}
}
var myObj = foo();
var addMe = 6;
alert(addMe);
myVar = 42;
myObj.bar();
alert(addMe);
This will display 6 and 20.
As far as I understand, any variable without the var keyword is treated global, with it, its local scoped, so:
// This is a local scoped variable.
var local_var = "something";
// This is a global scoped variable.
global_var = "something_else";
As a good JS practice, it is recommended to ALWAYS add the var keyword.
myVar=0;
function runMe(){
myVar = 10;
callMe();
}
function callMe(){
addMe = myVar+10;
}
As far as the output is concerned myVar and addMe both will be global variable in this case , as in javascript if you don't declare a variable with var then it implicitly declares it as global hence when you call runMe() then myVar will have the value 10 and addMe will have 20 .