Could anyone please explain this behavior of function inside another function? - 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();

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.

Javascript: global Var definition not at beginning [duplicate]

I understand Hoisting of variables is done in Java Script. I am unable to get why it outputs as undefined
do_something()
{
var foo = 2;
console.log(foo);
} do_something() // it prints 2
do_something()
{
console.log(foo); var foo = 2;
} do_something() // it prints undefined
As javascript do hoisting the second function also should print 2 as per my understand.buy why doesn't it
This is how the interpreter sees your code,
do_something() {
var foo;
console.log(foo); // undefined
foo = 2;
}
do_something();
So it is printing undefined. This is a basic of variable hoisting. Your declarations will be moved to the top, and your assignation will remain in the same place. And the case is different when you use let over var.
Javascript only hoists declarations, not initializations.
var x = y, y = 'A';
console.log(x + y); // undefinedA
Here, x and y are declared before any code is executed, the assignments occur later. At the time "x = y" is evaluated, y exists so no ReferenceError is thrown and its value is 'undefined'. So, x is assigned the undefined value. Then, y is assigned a value of 'A'. Consequently, after the first line, x === undefined && y === 'A', hence the result.
Variable Declaration
Only the declaration is hoisted. the assigned variables are not hoisted. So you are
The second function outputs undefined because you set the variable after you called it. The code you wrote is synchronous which means its read by the interpreter line by line, executed in order. If you don't define the variable before calling it, the console outputs undefined.
This article explains it in more detail.
Only the declaration is hoisted, any assignment to a variable always stays where its originally from.

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

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.

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;
}

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.

Categories