Javascript:why the result of the function about alert is undefined - javascript

var name="Jim";
var func=function(){
alert(name);
var name=true;
}
func();
var name="Jim";
var func=function(){
alert(name);
name=true;
}
func();
Two function has different results, can someone give me an explaination?

The reason this occurs is from hoisting. The variable declaration inside of your function scope is hoisted to the top. What this means is that your first function actually looks like this
var name="Jim";
var func=function(){
var name;
alert(name);
name=true;
}
func();
Which should make it more clear why undefined is alerted.
See "var hoisting" for a more in depth explanation.
Because variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it's declared. This behavior is called "hoisting", as it appears that the variable declaration is moved to the top of the function or global code.

Your first function is equivalent to:
var name="Jim";
var func=function(){
var name;
alert(name);
name=true;
}
func();
because variable declarations are always put by Javascript at the beginning of the scope. Therefore, when alert(name) is executed, name is undefined.
More information about scopes can be found in this answer.

Related

JavaScript Function Related Issue [duplicate]

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>

JavaScript scope in a try block

Say I'm trying to execute this JavaScript snippet. Assume the undeclared vars and methods are declared elsewhere, above, and that something and somethingElse evaluate to boolean-true.
try {
if(something) {
var magicVar = -1;
}
if(somethingElse) {
magicFunction(magicVar);
}
} catch(e) {
doSomethingWithError(e);
}
My question is: what is the scope of magicVar and is it okay to pass it into magicFunction as I've done?
Lots of other good answers about how Javascript handles this with var, but I thought I'd address the let situation...
If a variable is defined with let inside the try block, it will NOT be in scope inside the catch (or finally) block(s). It would need to be defined in the enclosing block.
For example, in the following code block, the console output will be "Outside":
let xyz = "Outside";
try {
let xyz = "Inside";
throw new Error("Blah");
} catch (err) {
console.log(xyz);
}
Javascript has function scope. That means that magicvar will exist from the beginning of the function it's declared in all the way to the end of that function, even if that statement doesn't ever execute. This is called variable hoisting. The same thing happens with functions declarations, which in turn is called function hoisting.
If the variable is declared in global scope, it will be visible to everything. This is part of the reason why global variables are considered evil in Javascript.
Your example will pass undefined into magicFunction if something is false, because magicVar hasn't been assigned to anything.
While this is technically valid Javascript, it's generally considered bad style and will not pass style checkers like jsLint. Extremely unintuitive Javascript like this will execute without any error
alert(a); //alerts "undefined"
var a;
POP QUIZ: What does the following code do?
(function() {
x = 2;
var x;
alert(x);
})();
alert(x);
In javascript only functions create a new context -closure.
Every definition of a variable is really a declaration of the variable at the top of its scope and an assignment at the place where the definition is.
var
function-scoped
hoist to the top of its function
redeclarations of the same name in the same scope are no-ops
You may want to read MDN scope cheat sheet
Due to hoisting You can even do things like this:
function bar() {
var x = "outer";
function foo() {
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
var x;
alert(x); // inner
}
foo();
}
bar();​
bar();​
Demo
So the foo function is converted to something like this:
function foo() {
var x;
alert(x); // {undefined} Doesn't refer to the outerscope x
// Due the the var hoising next:
x = 'inner';
alert(x); // inner
}​
My question is: what is the scope of magicVar and is it okay to pass it into magicFunction as I've done?
Define okay..., Yes the code is valid, but it's less readable then if the variables declarations were on the top, that's all.
Due to javascript "hoisting" (MDN description), your variable declaration code gets translated as:
function yourFunction() {
var magicVar;
try {
if(something) {
magicVar = -1;
}
if(somethingElse) {
magicFunction(magicVar);
}
} catch(e) {
doSomethingWithError(e);
}
} //end of your function
"Hoisting" moves all variables declarations to the top of the function. So magicVar is available everywhere in the function, but it's undefined until you give it a value.
Your variable has function scope.
With var, variables exist from the beginning of the function to the end of it, no matter where they are declared, or even if the statement is actually ever reached. They will, however, be undefined until they are assigned another value.
So in your case, if something is false but somethingelse is true, you will call magicFunction with its first argument being undefined.
The let keyword, created in Javascript 1.9 and available (as of today, May 3rd 2012, and as far as I know) only in Firefox, declares variables with the scoped semantics you're probably used to.
I agree with variable hoisting and function hoisting, I would like to emphasis two import points.
Identifier Defined in Catch parameter is i.e. err/e(error) , is scoped to Catch defined block.
Function first hoisting.
example :
b(); // output : 3
var b = 2;
function b(){
return 3;
}

Surprised that global variable has undefined value in JavaScript

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>

Why does shadowed variable evaluate to undefined when defined in outside scope?

Consider the following piece of code:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
}
f1();
</script>
</body>
</html>
The output for this code is that the alert box displays the message "outside
scope". But, if I slightly modify the code as:
<html><head></head>
<body>
<script type="text/javascript">
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
</script>
</body>
</html>
the alert box displays the message "undefined". I could have
understood the logic if it displays "undefined" in both the cases. But, that
is not happening. It displays "undefined" only in the second case. Why is this?
Thanks in advance for your help!
Variables are subject to hoisting. This means that regardless of where a variable is placed within a function, it is moved to the top of the scope in which it is defined.
For example:
var outside_scope = "outside scope";
function f1() {
alert(outside_scope) ;
var outside_scope = "inside scope";
}
f1();
Gets interpreted into:
var outside_scope = "outside scope";
function f1() {
var outside_scope; // is undefined
alert(outside_scope) ;
outside_scope = "inside scope";
}
f1();
Because of that, and the function only scope that JavaScript has, is recommended to declare all the variables at the top of the function, to resemble what will happen.
In the first case, your code is accessing the global variable "outside_scope", which has been initialized to "outside scope".
Javascript has function level scope, so in the second case it is accessing the function scoped variable "outside_scope", but it has not yet been initialized at the time of the alert box. So it displays undefined.
JavaScript has function scope, not block scope.
In the second case, the declaration of outside_scope is hoisted up to the top of the function (but the assignment isn't).
This is a great example of why JavaScript code is easier to read if you put all your variable declarations up at the top of the function. Your second example is equivalent to:
function f1() {
var outside_scope;
alert(outside_scope);
outside_scope = "inside scope";
}
and you can probably now understand why you're getting "undefined."
In the second example the local variable exists for the entire function scope. It doesn't matter that you defined it after the alert, it exists for the entire function.
However, the actual assignment doesn't occur until after the alert, hence the "undefined".
This is due to something called the hoisting of variable declarations.
Basically, JavaScript separates a variable declaration in two, leaving the assignment where you did the declaration and hoisting the actual declaration to the top of the function:
var f1 = function () {
// some code
var counter = 0;
// some more code
}
var f2 = function () {
var counter; // initialized with undefined
// some code
counter = 0;
// some more code
}
On run-time, f1() gets translated into f2(). I wrote an in depth blog post about this here. I hope this helps you understand what happens in your code.
This is also the reason, it is recommended to declare your variables at the top of a function in JavaScript. It helps you understand what the code does, when it runs.
that's an interesting case.
in the first example, you have defined a 'global' variable. it has global scope and is therefore accessible in any function/object for the execution.
in the second example, you have 'blocked' the global variable with the function scope variable, but since it hasn't been initialised yet at the time of the alert, it returns 'undefined'.
i agree this isn't the most intuitive quirk, but it does make sense.

Are variables statically or dynamically "scoped" in javascript?

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 .

Categories