2

I have a question on variable hoisting in JavaScript.

Consider the following example: ​

var myName = "Richard"; // Variable assignment (initialization)
​
​function myName () {
console.log ("Rich");
}
​
console.log(typeof myName); // string 

I am actually confused why typeof myName is returned as string.

As per my understanding, the example would be proceessed as below;

  1. First the function declaration (function myName ()) would get hoisted to the top and then
  2. JS interpreter would read the line var myName = "Richard" (since function declaration gets precedence over variable declaration). However, since there would already be a property with the name "myName", this statement would get ignored.

Thus typeof myName should get returned as function (and not string).

Where is my understanding incorrect?

halfer
  • 19,824
  • 17
  • 99
  • 186
copenndthagen
  • 49,230
  • 102
  • 290
  • 442

5 Answers5

1

JavaScript has a dynamic type system, i.e. the type of variables can change over time. Basically, what you write is correct: First, the function declaration gets run (on loading the file), but then the function stored in the variable myName is being overwritten by the string.

The only thing that gets ignored is the call to var, as the variable is actually already declared.

But it is perfectly valid to re-define a variable (and that's what you do here, by assigning a new value).

In the end, your sample is nothing but this:

var x = 23;
x = 'foo';

This will work as well, x will be 'foo', and its type is going to be string. The only difference to your sample is that in yours, a value of type function is involved.

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
0

In addition to the other answers what should be noted is that, if you declare your function in the following manner:

var myName = function() {
  console.log('Rich');
}

or simply

myName = function(){
  console.log('Rich')
}

as opposed to the "function myName . . . " syntax, then typeof myName will return "function"

johnsimer
  • 350
  • 3
  • 16
0

2 years passed, but perhaps it's still relevant to someone You are correct, when interpreting an object this is indeed so:

  • Scan the context for function declarations

    • For each function found, create a property in the variable object
    • If the function name exists already, the reference pointer value will be overwritten
  • Scan the context for variable declarations

    • For each variable declaration found, create a property in the variable object that is the variable name, and initialize the value as undefined
    • If the variable name already exists in the variable object, do nothing and continue scanning

However it looks like this is isn't so for global scope. I.e. when I define an object the output is exactly as it should be, when I define the same in the global scope it's not.... Still trying to wrap my head around this one

Mike Rodov
  • 569
  • 1
  • 4
  • 18
-1

Because of Hoisting your variables and functions definitions are moved to the top, so you have:

var myName;
// moved to top
function myName () {
  console.log ("Rich");
}

// next your code
myName = "Richard";

console.log(typeof myName); // string 

If you rewrite your code like this:

var myName = "Richard"; // Variable assignment (initialization)
​
myName = ​function () {  // Variable redefinition
  console.log ("Rich");
}
​
console.log(typeof myName); // function

Your myName variable now is a function, because only the myName variable is hoisted:

var myName;

myName = "Richard";     // Variable assignment (initialization)
myName = ​function () {  // Variable redefinition
  console.log ("Rich");
}
​
console.log(typeof myName); // outputs 'function'
TheGr8_Nik
  • 3,080
  • 4
  • 18
  • 33
  • You change from a function declaration to function expressions in your sample, and - unfortunately - they are treated differently by JavaScript: While the file is scanned for function declarations on loading, function expressions and their assignment get resolved at runtime. Hence your example unfortunately does explain something, but not what was asked. – Golo Roden Nov 04 '14 at 10:38
  • @GoloRoden - I have explained why the type of the `myName` variable is `string` and not `function`, next I have made an example where the type of the variable will be `function` ;-) – TheGr8_Nik Nov 04 '14 at 13:20
-1

The idea of "hoisting" is a bad way to understand what's going on. In other words, in my opinion "hoisting" is a bad explanation for hoisting.

What's really going on is not "hoisting". What's really going on is that javascript executes code in two phases: the compile phase and the eval phase. The javascript community calls the symptom of this "hoisting" but most people fail to understand why hoisting hoists because they think javascript interpreters have this feature called "hoisting" (they don't).

What actually happens is simpler to explain than the idea of hoisting. The rules are:

  1. Javascript always parse code from the top-down. It never reorders code (it never hoists).

  2. There are two phases of execution: compilation and evaluation.

  3. All declarations are processed in the compilation phase, no expressions will be evaluated in the compilation phase (because "evaluating" things are done in the evaluation phase).

  4. All expressions and anything else that need to be evaluated are processed in the evaluation phase.

Remember rule 1, all parsing are done top-down and there are no backtracking, no hoisting.

Let's take your example and try to understand it by keeping in mind javascript's compilation and evaluation phase:

    var myName = "Richard"; // Variable assignment (initialization)
​    
 ​   function myName () {
       console.log ("Rich");
    }

​    console.log(typeof myName); // string 
  1. In the compilation phase, the interpreter sees you declaring a variable. It allocates an area of memory for this variable and assigns it the value of undefined.

  2. In the compliation phase, the interpreter sees you declaring a function. It also notices that the function name shadows the variable name. So it creates a function "myName" (which means that at this point the variable myName points to the function).

  3. Compilation phase ends. Now we enter the evaluation phase.

  4. In the evaluation phase, the interpreter sees you assigning a string to myName.

  5. There is nothing to evaluate when we reach the function declaration because declarations are processed in the compilation phase.

  6. In the evaluation phase, the interpreter sees you console.logging the typeof myName. Since the last thing assigned to it was a string it prints "string".

Note that if you remove the string assignment then myName will be typeof "function". That's because in that case the last thing assigned to it is the declared function.

See this related question for other subtleties caused by the two phases of execution: JavaScript function declaration and evaluation order

Community
  • 1
  • 1
slebetman
  • 109,858
  • 19
  • 140
  • 171
  • 1
    I don't think your explanation is correct. "Hoisting" is a language feature and although the standard doesn't use that very word, the procedure is documented precisely -- see "Declaration Binding Instantiation" http://ecma-international.org/ecma-262/5.1/#sec-10.5 – georg Nov 04 '14 at 07:55