Javascript Function Scope Confusion - javascript

Can someone explain this to me:
var test = 5;
// prints 5;
function printMe1(){
console.log(test);
}
// prints "undefined"
function printMe2(){
console.log(test);
var test = 10;
}
Is this because printMe2 creates a local variable of "test"? And if so, why does the log statement refer to the local variable, if it is declared after it?
And also, if JS is an interpreted language, shouldn't the code be interpreted line by line? In which case the log statement shouldn't be able to know that the local "test" variable is declared later?

there is a concept in javascript "hoisting" so in hoisting variables and function declarations are moved to the top of their scope before code execution. remember only declaration, not the definition. that's why in your code var test is showing undefined because you are using this variable before defining it.
var test;
function printme2(){
console.log(test)
test=10
}
printme2()

I just did some googling and found the answer.
It is because Javascript "hoists" variable declarations to the top of the scope. So the local "test" variable was declared at the top of the function scope, thus the reason why printing it gave "undefined".
(if any of this wrong let me know please :) )

Related

Why variables of function declared outside through "." accessible only through "." inside the function?

I initialized a variable of function through "." outside the function. Regarding closure rule, it should be set inside the function scope and after execution should be gone. But
Why after calling the function variable still exists?
Why can I access inside a function only through "."?
I initialized variable outside of the function through "." like f1.a = "any variable".
I checked if the variable of function initialized outside is accessible inside a function without ".":
I tried to get access to the variable inside the function. It seems if I get access to the variable by itself without "." it gives me an error "variable is not defined".
I checked if the variable of function initialized outside will be gone after function execution:
I call function and check if the value of the variable after execution is still available. Yes, it was still there.
f1.a = "any variable";
function f1(){
(function()
{
console.log(a);
}()) // a is not defined
}
f1();
console.log(f1.a); // after f1(), f1.a still exist
I expected variable "a" visible by itself inside the "f1" since I initialized inside the function scope f1.a = "any variable", but I can get access only with "."
I expected variable "a" will be gone after execution f1(), but it still exists
There are several things you need to understand to get a clear idea of what's happening here. First, JavaScript hoists function definitions to the top of the file.
Knowing that, you could imagine your code is something like this once JavaScript interprets it:
var f1 = function (){
(function()
{
console.log(a);
}()) // a is not defined
}
f1.a = "any variable"
f1();
console.log(f1.a);
Secondly, in your first console.log(a) you are referencing a variable a which was never declared. If you change that to console.log(f1.a) you'll see the value of f1.a as expected.
It's also not clear why you are using an immediately invoked function inside of your f1 function. It makes analyzing this code even more complex. It seems like you are trying to get a better understanding of how closures work? But for closures you should be interested in variables declared inside of f1, rather than properties of f1. For example, something like this.
f1 = function (){
var a = 'something'
return function()
{
console.log(a);
}
}
var closure = f1();
// f1 is finished running here.
closure(); // closure still has access to f1's variable.
I think the three areas you could learn more about to understand the code above are 1. Scope and especially hoisting 2. Objects, this and object properties and 3. Closures.

cannot read a variable from the global context

JS:
var a = 10;
function test() {
alert(a);
var a = 20;
alert(a);
}
test();
The above code was discussed earlier with an interviewer yesterday, i said first time browser would alert 10 and for the next time it would alert 20, but i was wrong. It alerted undefined for the first time and 20 for the second time. I am confused and can anybody theoretically as well as practically explain what's going behind this..?
Relevant link would be very helpful.
DEMO
In a function, every var is treated as if it appeared at the very top of the function. Thus your code is interpreted as if it were written:
function test() {
var a;
alert(a);
a = 20;
alert(a);
}
It's called hoisting. Note that it's the declaration that's hoisted, not the initialization assignment.
The effect here is that everywhere inside that function, a refers to the local variable, which hides the relatively global a from view.
Here is the relevant section of the ES5 spec. It's somewhat opaque.
When your variable is found in the local scope of the function then it doesnt refer to the global variable. The scope of the global variable is hidden inside the function and hence you are getting the undefined value for the first time.
This concept is called Hoisting ie, In JavaScript, a variable can be declared after it has been used. In other words; a variable can be used before it has been declared.

Javascript Odd Scoping Behavior

I've been going through Javascript function scope and have run into this:
var scope = "global";
function f(){
console.log(scope);
var scope = "local";
console.log(scope);
}
f();
Now I understand that the output of the first log is "undefined" because of how js hoists variables at the top of the function. BUT when I remove var from "var scope = "local";" the first log outputs "global" and this has got me scratching my head. Can someone explain why that is happening please? I mean doesn't js sequentially run the code? As such how can removing VAR have any impact on the first log?
Two-pass parsing. The code will be treated as if it was
function f() {
var scope; // var created, but no value assigned. this overrides the earlier global
console.log(scope);
scope = 'local';
console.log(scope);
}
The var's CREATION will be executed as if it was the very first bit of code executed in the function. But the actual assignment operation won't occur until where it normally would.
Javascript sometimes behaves a bit differently from other languages. Take a look at http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html, they explain it a bit.
If you omit the var statement, the first log uses the global variable, which is set with the string "global". There is no other local variable and no hoisting.
First log: global variable scope set with "global" content
Assignment of new string for the same global variable
Second log: global variable scope set with "local" content

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.

scope in javascript

i have encountered the following curious piece of code:
function foo(){
works = {hello:"world"};
function bar(){
alert('does not work');
}
var notwork = {hello:"world"};
}
foo();
alert(works.hello);
alert(notwork.hello);
Can someone please explain to me why works work, and notwork doesn't work? Or point me out to a good resource that explains this in detail.
Thank you very much!
var notwork creates a local variable valid only for the runtime of the function.
works creates a global variable that is valid throughout the javascript runtime.
var declares a variable as "local" to the function it's defined in.
Without var, you works variable is global : it can be seen/accessed/used from anywhere.
With var, your notwork variable is local to the foo function : it cannot be seen/used from outside of that function.
For more informations, you can take a look at the documentation of the var statement on MDC, which states (quoting) :
The scope of a variable is the current
function or, for variables declared
outside a function, the current
application.
Using var outside a function is
optional; assigning a value to an
undeclared variable implicitly
declares it as a global variable.
However, it is recommended to always
use var, and it is necessary within
functions in the following situations:
If a variable in a scope containing the function (including the global
scope) has the same name.
If recursive or multiple functions use variables with the same name and
intend those variables to be local.
Failure to declare the variable in
these cases will very likely lead to
unexpected results.
You've missed out the var keyword so works is being defined on the global object.
You want
var works = ...

Categories