Javascript: global Var definition not at beginning [duplicate] - javascript

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.

Related

Issue with let keyword

I was playing with some code and ran into a situation where I couldn't identify why 'let' is behaving the way it does.
For the below block of code:
var x = 20; // global scope
function f() {
let x = x || 30;
}
f(); // VM3426:1 Uncaught ReferenceError: x is not defined(…)
I get the error 'x is not defined' on executing f(). I do understand 'let' variables are not hoisted but since 'x' has a global copy, why isn't the line inside function 'f' defaulting to global copy instead of throwing an error?
Does 'let' set the variable to undeclared (instead of 'undefined' with var because of hoisting) at the beginning of the function?
Is there any way to get the global copy of 'x' within the function?
The exception is about the right side x - when you are initializing block-scope x variable the global one is already "forgotten" however the new one is still not being declared and cannot be used during initialization
Compare with explicit calling global one
function f() {
let x = window.x || 30;
}
Also take a look at this MDN article about let dead zones
let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope.
Here in your case, an exception is thrown because you are defining let with the same name.
For More Info
you can use this keyword to access global scope
var x= 20; // global scope
function f() {
let x =this.x || 30;
}
f();
but In strict mode this will default undefined
Read it https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/this
The declaration of the local x is shadowing the global one and new one is still not declared first and cannot be used during initialization. It is same situation like following :
var foo = 5;
function do_something() {
console.log(foo); // ReferenceError
let foo = 2;
}
do_something();
For reference MDN
As suggested by #m.antkowicz you can use window.x in your case.

Javascript Hoisting : difference between calling x and window.x

Can anyone explain the hoisting behavior in the below scenarios?
alert(x);
var x = 10;
Result: alert-undefined
In the below case, x is not defined using 'var' keyword - hence attaches to the global scope.
alert(x);
x = 10; // not given a var
Result: error
In case if we replace x with window.x, we get alert as undefined!
alert(window.x); // calling the variable with window namespace
x = 10; // not given a var
Result: alert-undefined
Can you explain why it is different in calling a variable (which is attached to global scope) with the variable name (x) and with window namespace (window.x)?
The term "hoisting" is often misunderstood to mean that certain statements are moved to the top of their execution context, which is not what happens and why the term should be avoided.
What actually happens is that all declarations are processed first, so any variable declared with var (and any function created by a function declaration) exists before any code is executed. Then code execution begins.
So the variable x is created and assigned the value undefined before any code is executed (per ECMA-262), then later, during execution, it may be assigned some value.
So in the case of:
alert(x);
var x = 10;
x exists when alert is called, but has yet to be assigned a value other than undefined.
In:
alert(x);
x = 10;
x is not declared, so it does not exist when alert is called, hence the error. After the alert (if the code kept running), the assignment to x would create a property of the global (window in a browser) object named x and assign it a value of 10.
In:
alert(window.x);
x = 10;
It is a quirk of ECMAScript that global variables are also available as properties of the global object. The expression window.x attempts to read the x property of the window object. Since no such property exists, the return is undefined. Then the next statement creates x as a global variable and hence window.x now exists with a value of 10.
var x hoists the variable in the entire scope it's valid in, so the name x is available and valid anywhere within the scope. Its initial value is undefined, it only receives its value after the alert.
In case of a plain x, the variable is not hoisted because there's no var, so the bubbling up to window and its creation there only happens on the line x = 10, which is after the alert, which means the variable is entirely undefined and invalid at the time you try to alert it.
Any non-existing property of any object returns undefined, so testing window.x at a time when that property isn't set returns undefined as expected. That's how you do membership testing in Javascript: check whether a specific property equals undefined.
In the first case, var x gets hoisted, so x does exist when you call it (even though the value is undefined)
In the second case, when you say y = 10, you're essentially saying window.y = 10, so there's no hoisting at all, that's why it can't find the variable at all and gives you an error.
alert(x);
var x = 10;
will treated as
var x;
alert(x);
x = 10;
So at the time of alert x has the value undefined by default;
alert(x);
x = 10;
will be treated as
alert(x);
x = 10; // If this line runs in use strict mode then this line will throw error otherwise in non strict mode x will be added to global object ie. window
So will throw error because of x is undefined at the time of alert
alert(window.x);
x = 10;
will be treated as
alert(window.x);
x = 10;
alert will alert undefined because window is an object and it is having no property named as x at the time of alert so undefined
Later the line x = 10; will add the x to global object if in non strict mode, and will throw error if in strict mode

Some complex behaviour with 'with' statement and call

var a = ({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
Results in undefined, 30, 20.
Would be greatly appreciated to get some step by step debug-style explanation of how this works.
OK, lets first simplify the code a little. I've refactored out that foo is a method, which is not necessary do demonstrate the unexpected behaviour.
function foo(a) {
// var x, y, bar - hoisting
function bar() {
console.log(x);
console.log(y);
console.log(a.x);
}
with (a) {
var x = 20;
var y = 30;
bar();
}
}
foo({x:10});
So what happens when we call foo?
An execution context is set up and filled with the declared functions and variables. This is what colloquially is referred to as "hoisting". In foo, there are the function bar and the variables x and y (and the function foo itself and its argument a, only in my refactored version). This is the scope to which bar has access to.
The with statement is executed. It exchanges the current lexical environment with one that is based on the a object - any properties of that are accessible like variables now.
The value 20 is assigned to an x. What is this x? When resolving that identifier, the a object is checked and - oh - it has a binding with that name! So we put the value in that binding, which will put the 20 on the .x property of the object.
The value 30 is assigned to an y. What is this y? Again, the current lexical environment is checked but we don't find an y property on the a object. So we go on to the parent environment, which is the one with the x, y, bar variables created above. Indeed, here we find an y variable, so we put the value 30 in that slot.
The bar function is called. Again, a new execution context is set up (like above), with the one from step 1 as its parent scope (which was determined by the lexical position of bar in foo, when the bar function was instantiated - lexical closure). Now we log those three expression of interest:
x resolves to the variable x in the scope of foo, which still has the value undefined.
y resolves to the variable y in the scope of foo, which holds the value 30 that we just assigned.
a.x resolves to the x property of the a object, which holds the value 20 that we just assigned.
It's generally recommended that you avoid with. It's confusing!
That said, it's probably simplest if we just annotate your code. I'll refer to your anonymous object as {} instead of this to avoid ambiguity. And the switch in the ordering here is solely for the sake of reading the code in execution order from top to bottom.
var a = ({
x: 10,
foo: function () {
// entering `with(this)`: all variables are searched against `{}`
// before the engine attempts to create a new variable:
with (this) {
// `var x` creates a local `x`. But, during assignment,
// `x` matches `{}.x`, so `{}.x` is set. **local `x`**
// remains `undefined`.
var x = 20;
// `y` isn't found in `{}`, so it's a local variable
var y = 30;
// execute `bar()`
bar.call(this);
}
// we're now in scope of `{}.foo()`, but not `with(this)`.
function bar() {
// local variable `x` was declared, but never defined.
console.log(x);
// local variable `y` exists in the scope of `{}.foo()`
console.log(y);
// we're still in the "macro" scope of `{}`. So, `this` refers
// to `{}`, which was changed to 20.
console.log(this.x);
}
}
}).foo();
Clear as mud? (Don't use with if you can avoid it!)

Could anyone please explain this behavior of function inside another function?

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();

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

Categories