Javascript Hoisting : difference between calling x and window.x - javascript

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

Related

Why does a `let` assignment that uses the same variable name in its right-hand side throw a ReferenceError? [duplicate]

This question already has answers here:
What is the temporal dead zone?
(3 answers)
Closed 5 years ago.
I’m sure it’s a little caveat somewhere but, here is the issue:
var x = x || {}; // Works!
let y = y || {}; // ReferenceError: can't access lexical declaration 'y' before initialization
const z = z || {}; // ReferenceError: can't access lexical declaration 'z' before initialization
The let and const cases throw “ReferenceError: can't access lexical declaration 'variableName' before initialization”.
What is going on here? I can kind of understand the const one, but how is let not working either?
Variables declared with var are hoisted to the top of the enclosing function or global scope. They are assigned the initial value of undefined. Hence the example line of code var x = x || {}; is transformed by hoisting and default value initialization into this equivalent code:
var x = undefined;
x = x || {};
Because x already has a value when the right-hand side of the assignment statement is evaluated, the code proceeds normally.
Side note: You can declare a variable with var even after the first assignment (due to top-hoisting), and declaring more than once is idempotent (e.g. var x; var x;).
Variables declared with let and const are hoisted to the top of the enclosing block, but are not given a default value. If such a variable is read before a value is assigned, a ReferenceError is thrown. Your example line of code is transformed by hoisting into this equivalent code:
let y;
y = y || {};
To execute the assignment statement, the right side is first evaluated, then its value is assigned to the variable on the left side. But in this case, the right side reads y, which has not been assigned a value yet — hence an error is thrown.
Everything that is in the same scope as the let statement, but executed earlier (i.e. above let or the right-hand side of a let assignment) is within the Temporal Dead Zone (TDZ).
Note that in JavaScript, a piece of code like let x = x + 1; throws an exception only if execution reaches that statement. Whereas in other languages like Java, the same piece of code is always a compile-time error, even if it’s buried inside an if(false){...}. This emphasizes the behavior of variable hosting, and the fact that JavaScript examines what the code means when it is executed, hence these examples are not syntax errors in a strict sense.

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.

Value of variable changes when page reloads

While coding for simple function declaration, there is a strange behavior by Firefox Scratchpad.
console.log(x);
var x = 0;
var func = function() {
console.log(y);
var y = 1;
};
func();
When I executed above code first time with Run, it gave result as below :
undefined undefined
But when I executed it second time, it gave below result :
0 undefined
So I assumed that the value must saved in cache, but then why wasn't the variable y still undefined?
Also when I repeated it with Reload and Run, the first result was repeated.
Its all about var top-hoisting. and function's block scope
When you run the first time your code actually look like this one.
var x;
console.log(x); // undefined as still x is not defined
x = 0;
var func = function() {
var y;
console.log(y); //undefined as still y is not defined
y = 1;
};
func();
Now,when you re-run second time,status of func() is not going to change as it redefined the block scope of func
So at second run
var func = function() {
var y;
console.log(y); //undefined as still y is not defined
//as scope is re-initializd
y = 1;
};
In javascript,every function when invoked, create a new execution context
but as var x; declared and defined in global scope during first time executiion,it is fetched from there. so, x=0 and y=undefined
Since first time when you execute that time there is no x and y variable declared before using it.
As soon as it comes to second line x is declared as global which remains in your page scripts. but in case of y variable, it is declared inside the function, its scope limited to function only hence y is not going to be global.
Hence when you refresh your page that time x variable gets that global value but not in case of y.
Its all about scope of variable in Javascript

What's the difference between variable definition and declaration in JavaScript?

Is this a variable definition or declaration? And why?
var x;
..and is the memory reserved for x after this statement?
EDIT:
In C extern int x; is a declaration, int x = 5; is a definition. What's the analog in JS? Wikipedia says a declaration allocates memory and the definition assigns a value to this allocated memory.
SECOND EDIT:
I think the explanation of #Deryck sounds great, but there's some output that disagrees with his explanation:
> var x;
undefined
> x
undefined // now it looks like x is defined to the value undefined
> y
ReferenceError: y is not defined
If the ReferenceError output would say y is not declared it would make sense. But often I read that JS has two non-values: null and undefined. So var x would be a definition with the value undefined.
var x is a declaration because you are not defining what value it holds but you are declaring its existence and the need for memory allocation.
var x = 1 is both declaration and definition but are separated with x being declared in the beginning while its definition comes at the line specified (variable assignments happen inline).
I see that you already understand the concept of hoisting but for those that don't, Javascript takes every variable and function declaration and brings it to the top (of its corresponding scope) then trickles down assigning them in order.
You seem to know most of this already though. Here's a great resource if you want some advanced, in-depth exploration. Yet I have a feeling you've been there before.
Javascript Garden
PS - your analogy between C variable dec/def and JS was spot on. What you read on Wikipedia was correct.
Declaring a variable is like telling the (javascript) compiler that this token x is something I want to use later. It does point to a location in memory, but it does not yet contain a value. ie. it is undefined
var x;
defining it means to give it a value which you can either do it like:
x = 10; // defining a variable that was declared previously
or like this:
var y = 20; // declaring and defining a variable altogether.
http://msdn.microsoft.com/en-us/library/67defydd(v=vs.94).aspx
http://www.w3schools.com/js/js_variables.asp
I will give you a long answer for better explanation.
When the javascript engine is not able to find a particular variable in memory, it will throw an error. To be more specific, when the javascript engine (Execution Context) is not able to "reference" a variable in memory, it will throw a ReferenceError. This is not exactly the same as a Declaration Error, at least in javascript.
There is a deference between a not defined error and the value undefined.
So doing
var a = undefined;
and
var a;
will both log the same result i.e. undefined. This is because, when you simply do a var a; the javascript engine allocates memory for the variable and automatically sets it's value to undefined, which is different from saying that a doesn't exist at all - in which case it will throw a ReferenceError.
Hoisting
console.log(a); // undefined
var a = 'something';
will log undefined because, the javascript engine knows there's a variable declared somewhere in the code - which means to say that the javascript engine actually does something before it executes the code - one of the thing it does is hoists variables. To put it simply, the above code is the same as
var a; // hoisted (declared and defined the value `undefined`)
console.log(a); // undefined
a = 'something' // update the defined value to `something`
So, yes, declaration and definition happen together in javascript (automatically - if you don't do it yourself) and the default defined value is undefined.
ES6
Just an additional note
const a;
will throw a SyntaxError where a initializer (definition) is necessary. const is the only time when you need to declare and define manually.
> var x;
undefined
> x
undefined // now it looks like x is defined to the value undefined
> y
ReferenceError: y is not defined
Although it is usually said that Javascript is an interpreted language, but there is also a compilation step that happens very fast just before the interpreter runs. The job of this compilation step is to create scope chains, where variables are declared(no read/write operation here, just simple name-keeping) in their respective scopes. These variables will point to some memory location but value in it will be undefined until some execution is carried out by the interpreter.
> Compiler run:
When compiler sees var x;, it will simply book-keep this variable in its respective scope.
The next x; and y; are simply ignored in the compilation step as they are execution statements.
> Interpreter run:
When interpreter sees var x;, it will skip this as there is no read/write operation here.
Now when interpreter sees x;(execution statement), "x" will already be declared in the scope, and it will hold value "undefined", which is what you get on the console.
But when interpreter sees y; similarly, there has been no previous declaration or name-keeping for it in the compilation step, and thus we get the ReferenceError as expected.
Hope someone finds this comment useful.
var x, y, z;
var x;
var h = 4;
i = 4;
all the above are global variables if placed at the top, (outside any functions)
Lets say that the javascript has a function start
function start() {
x = 5*5;
}
the global variable x is now equal to 25
Where as if the var x; was not placed outside of any functions, that variable x would just be local to that function.
You declare JavaScript variables with the var keyword:
var carname;
After the declaration, the variable is empty (it has no value).
To assign a value to the variable, use the equal sign
var carname="Volvo";
In computer programs, variables are often declared without a value. The value can be something that has to be calculated, or something that will be provided later, like user input. Variable declared without a value will have the value undefined.
The variable carname will have the value undefined after the execution of the following statement:
var carname;
var hoisting
In JavaScript, a variable can be declared after being used.
bla = 2
var bla;
// ...
// is implicitly understood as:
var bla;
bla = 2;
For that reason, it is recommended to always declare variable at the top of functions. Otherwise, it may lead to confusing cases
When declaring a variable without assigning a value to it, there still needs to be some memory available for it, otherwise you cannot make a reference to the variable later in the program. I don't think it's a noticeable amount of memory being used and won't make a difference.
var x;
This is a variable declaration. In Js if you don't assign any value to variable in declaration. It will get undefined by default.
var x; // declaring x
console.log(x); // output: undefined
But if you have not even declared the variable in you try to access it. It says that the variable is not defined.
console.log(y); // Output: ReferenceError: y is not defined
If you need access to objects between JS files, it's good practice to expose one object to the global namespace and declare fields and methods on that object.
File 1:
var myObject;
myObject.myField = "Field!";
File 2:
myObject.prototype.myFunction = function () {
return this.myField;
};
I have taken from a really good discussion on : Equivalent of C extern declaration in JavaScript
https://github.com/ganqqwerty/123-Essential-JavaScript-Interview-Questions
Various trivia regarding the difference between undefined and null completely aside, the short answer is: there is no equivalence in Javascript. There are no bare "forward declarations". Javascript variable declarations are definitions. Variables that have been defined but not explicitly initialized will contain the value 'undefined'. There is no "external linkage".
If you refer to an identifier that is not in any accessible scope (perhaps because it doesn't exist the first place), you will get your "ReferenceError: y is not defined". This has nothing to do with variable value or storage.
In simple terms,
undefined means value to the variable is not defined.
not defined means the variable itself is not defined.
var x; //value is not defined. So,
x //undefined
//y variable is not declared or defined. So,
y // y is not defined

Value returned by the assignment

Why does the regular assignment statement (say, x = 5) return the value assigned (5 in this case), while the assignment combined with a variable declaration (var x = 5) returns undefined?
I got the return values by executing these statements in the Chrome browser's Javascript console:
> var x = 5;
undefined
> y = 5;
5
That's the way the language was designed. It is consistent with most languages.
Having a variable declaration return anything other than undefined is meaningless, because you can't ever use the var keyword in an expression context.
Having assignment be an expression not a statement is useful when you want to set many variable to the same value at once:
x = y = z = 2;
It can also be used like this:
x = 2*(y = z); // Set y = z, and x = 2*z
However that is not the most readable code and it would probably be better written as:
y = z;
x = 2*z;
That's because var x = 5; is a variable statement, not an expression.
The behaviour of this statement is described in Section 12.2 of the ECMAScript Language Reference.
Evaluate VariableDeclarationList.
Return (normal, empty, empty).
This is basically a void return value.
The assignment operator (i.e., the equals sign) (1) assigns the right-side-operand (i.e., a value or the value of a variable, property, or function) to the left-side-operand (i.e., variable or property) and then (2) the assignment expression (e.g., y = 10) becomes a simple operand with the same value as its right-side-operand (e.g., 10) before the rest of the expression is evaluated. This is similar to when a called function is replaced with its return value when an expression is evaluated (although function calls are first in the order of operations and assignment operations are fourteenth):
var x, y, z = 1;
x = z + (y = 2); // x === 3
function returnTwo () {
return 2;
}
x = z + returnTwo(); // x === 3
Take note that not only does x now equal 3, but the entire expression evaluates to 3.
The purpose of the var keyword is to bind variables to the current scope. Variables declared with the var keyword are bound to the scope where they are declared. The var keyword assigns the left-most variable (or property) as a reference to the value of the evaluated expression:
var fun = function () {
var x = 1;
var y = x + 1;
return y;
}
// The x and y variables are bound to the scope of the fun function.
Using the var keyword with an expression is called a declaration. Declarations are actions that do not evaluate to a value, not even undefined (even though your console is printing undefined). Further, declarations cannot appear where JavaScript expects an expression, as other answers to this post have shown.
When you write var x = 5; it declares x and initalizes its value to 5.
This is a VariableStatement, it returns nothing,
but x=5 is an expression that assigns 5 to x.
as there is no x, JavaScript implicitly creates a global x in normal code
I edited my answer because of comment and some other answers.
Assignment operator doesn't return anything... In below example, first thing JS parser does is assigning 5 to y. Second thing is assigning y to x, and so on. Assigning is not return (it's not a function, and in JS it doesn't have C++ syntax to overload operator's behavior). return is sth more complex then assignment. return construct is not only returning a value, but is closing current context causing it to be destroyed. Also it's closing any parent context (closure pattern) if there is no other child using it. So please, DO NOT tell me (in comments) that assignment operator returns any value. Assignment operator in case of JS is only a language construct.
This language construct is useful in chains (and that's why everyone is talking about returning):
a = x = y = 5;
Any undeclared variable is declared automatically by parser in global scope. If you declare variable explicitly, then you can't at the same time use it in chain, like this:
a = var x = y = 5;
Proper use of above code would be:
var x = y = 5;
a = x;
Of course you can use brackets, to make your code clearer, but it doesn't mean that code behaves like a function.
Also your example works only in JS console, which is not returning but printing the result of statement, or expression. It means that JS console treats result of declaring of variable as undefined (same when creating function: function a() {}).

Categories