Veverke Veverke - 1 year ago 78
Javascript Question

Javascript hoisting and variable assignment (with no declaration)

Looking at MDN's introduction to JavaScript, Grammar and Types section - one reads:


Declaring variables



You can declare a variable in three ways:


  • With the keyword var. For example, var x = 42. This syntax can be used to declare both local and global variables.

  • By simply assigning it a value. For example, x = 42. This always declares a global variable. It generates a strict JavaScript
    warning. You shouldn't use this variant.

  • With the keyword let. For example, let y = 13. This syntax can be used to declare a block scope local variable. See Variable scope
    below.




The following code snippet would seem to fit the "by simply assigning it a value" scenario, meaning the variable should be treated as global.

(function(){
console.log(myVar);
//the following will throw a ReferenceException error
//myVar = 10;

//the following will not, and I can understand it following the defintion of the behavior of using `var` keyword
//var myVar = 10;
})();


But running the code will generate a ReferenceException when
myVar
is commented, and undefined when not. I would expect it to generate undefined in both cases, since if
myVar
is a global variable (per definition), than javascript's variable hoisting would make it known before reaching
console.log(myVar);


What is the explanation behind such behavior ? (the behavior I described is what I get when trying it in my firefox's console, but running it in
jsfiddle
will not throw an error).

Are self-executing functions an exception to hoisting ?

Answer Source

the "by simply assigning it a value" scenario

You are reading the value, not assigning it

if myVar is a global variable (per definition),

It isn't.

myVar is:

  • a variable scoped to the function if the function contains var myVar (or function myVar () { ... }, or it is listed as a parameter in the function definition).
  • a variable scoped to the block if the block contains let myVar
  • a global variable if a value has been assigned to it previously and neither of the above conditions are true.

Since you haven't assigned a value, it isn't a global. Since none of the above conditions are true, it isn't any kind of variable, so you get a reference error.


Regarding your comment:

I left my var when I meant var in the scenario I am trying to depict. Updated question.

… and the edit to which you refer:

Commented out code is not evaluated. Having a comment that uses the keyword var doesn't do anything.


Regarding your further edits.

You get a reference error if you try to read a variable before it has been declared.

var statements (and function declarations) are hoisted so a variable declared with those methods can be read anywhere in the function.

Assignments are not hoisted. A global variable created implicitly by assignment (which is generally not considered to be best practise and is banned in strict mode) can't be read before the value is assigned.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download