5

Since I am a JavaScript newbie, I started learning it but I got stuck just at the beginning. I am following a Mozilla Tutorial and I have a problem with variable scope in JavaScript. I have some code:

var myvar = "my value";
var zmienna = "string";
(function () {
 alert(myvar);
 alert(zmienna);
})();
(function () {
 alert(myvar); // undefined
 var myvar = "local value";
 alert(zmienna);
})();

In the tutorial, I've read that JavaScript variables are not visible from function blocks. Well, first two alerts says correct values. It's strange then, because third alert says "undefined", despite fact that nothing has changed from previous function block. The fourth one, again, prints right value.

Could anybody explain me, what is happening here? I would be very glad, because tutorial says nothing more about that.

ckittel
6,7164 gold badges43 silver badges71 bronze badges
asked Aug 26, 2011 at 15:24
1
  • "I've read that JavaScript variables are not visible from function blocks." Where is that in the tutorial? That sentence just does not make sense. Commented Aug 26, 2011 at 15:40

2 Answers 2

9

The use of var is hoisted.

Since you have var myvar inside the function, there is a locally scoped myvar. Since you assign a value to it after you alert it, it is undefined when you alert it.

answered Aug 26, 2011 at 15:26
Sign up to request clarification or add additional context in comments.

5 Comments

Okay, thank you. But why the first two alerts show correct value, despite that tutorial says different (as I understood, thay should have been "undefined" since thay are in different scope). Could you explain me that ?
Because you have myvar and zmienna declared in global scope. So they are accessible from anywhere in your script, if not hidden by local scope definitions.
@Quentin: Maybe show OP the equivalent code that demonstrates to a beginner what "hoisted" means and how the declaration is hoisted but the assignment is not.
Thanks for answer. Of course, I don't want to argue, but does Mozilla tutorial says wrong ? It's quite strange, because they say "myvar" should be not accessible and you say different. It's quite hard to understand :)
As long as you haven't used the keyword var inside your function the value will be that of the global variable, which in your example would be the first var myvar = "my value" (line 1). Because you've used the keyword var in your second function (line 13), the value is undefined at the alert (line 12) because var myvar; will be "hoisted" to the top of the function . See Example 2 of the tutorial linked to in your question.
1

"I've read that JavaScript variables are not visible from function blocks."

That's not quite right. They are available from the nested functions.

Nested functions create a scope chain. A function created inside another function has access to its own variables as well as the variables of the function in which it was nested.

But function A can not see the variables of function B if function A was not nested inside function B.

var myvar = "my value"; // <-- global variable, seen by all functions 
var zmienna = "string"; // <-- global variable, seen by all functions
(function () {
 alert(myvar); // <-- referencing the global variable
 alert(zmienna); // <-- referencing the global variable
})();
(function () {
 // v--- Declaration of these "local" variables were hoisted to the top...
 // var myvar; // <--- ...as though it was here.
 // var new_var; // <--- ...as though it was here.
 alert(myvar); // undefined (myvar is delcared, but not initialized)
 alert(new_var); // undefined (new_var is delcared, but not initialized)
 var myvar = "local value"; // <-- assign the value
 alert(zmienna); // <-- referencing the global variable
 alert(myvar); // <-- referencing the local variable
 var new_var = "test"; // <-- another new local variable
 // A nested function. It has access to the variables in its scope chain.
 (function() {
 alert(myvar); // <-- referencing the variable from its parent func
 alert(new_var); // <-- referencing the variable from its parent func
 })();
})();
/* 
Here's a new function. It was not nested inside the previous function, so it
 has access to the global variables, and not the locals of the previous func
*/
(function () {
 alert(myvar); // <-- referencing the global variable
 alert(new_var); // <-- ReferenceError
})();
answered Aug 26, 2011 at 15:47

4 Comments

Thank you very much for your answer. Now it seems to be logical. Although, I must admit, for me, Javascript is a lot harder that other languages that I have some knowledge of (mainly C++, PHP and Erlang). Thank you once more.
@Radi: You're welcome. I have a some knowledge of Erlang, but not the other two. This phenomenon is called shadowing, where a nested function can declare a variable with the same name as a variable in its parent, and so which value you get depends on which level of the scope chain you're in since the nested ones block access to those of the ancestors. If I recall, Erlang doesn't allow shadowing because of its strong typing, but I may not be remembering correctly.
Well, to be honest, it is possible to shadow variable in Erlang, although compiler warns you about that (check this: gist.github.com/1173877)
Ah, thanks @Radi. I've only messed with Erlang briefly a couple of times. I just remember that I really liked it, but didn't have a practical application for it at the time. I'm sure I'll do some more tinkering one of these weeks. :)

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.