3

I'm trying to wrap my head around a few things when it comes to hoisting and variable mutation.

  1. Variable assignment takes precedence over function declaration
  2. Function declarations take precedence over variable declarations

Function declarations are hoisted over variable declarations but not over variable assignments according to https://scotch.io/tutorials/understanding-hoisting-in-javascript. This is extremely confusing because I thought only variable declarations and function declarations get hoisted.

var double = 22;

function double(num) {
 return (num*2);
}

console.log(typeof double); // Output: number

so with hoisting it should look like

function double(num) {
  return (num*2);
}

var double;
double = 22;


console.log(typeof double); // Output: number

If variable assignment takes precedence over function declaration why isn't double = 22 above the function declaration? Another example

var double;

function double(num) {
  return (num*2);
}

console.log(typeof double); // Output: function

With hoisting pulling the function above the variable declaration the console should log undefined shouldn't it? With variable mutation the last assignment is what the program should execute.

larry burns
  • 189
  • 1
  • 9
  • 4
    Variable *name declarations* are hoisted, but variable *assignment* (with `=`) is never hoisted – CertainPerformance Dec 22 '18 at 21:52
  • Then what does "Variable assignment takes precedence over function declaration" mean? – larry burns Dec 22 '18 at 21:57
  • 3
    @larryburns It makes no sense at all, really. An assignment and a declaration are two totally unrelated things, they don't "take precedence" over each other. I guess it's supposed to mean just that you can always assign a mutable variable, and it will hold the assigned value afterwards, regardless of where/how the variable was declared (with `var` or `function`). – Bergi Dec 22 '18 at 21:57
  • Can anyone explain how in my last example even though function is hoisted above the variable declaration the output is still function instead of undefined? – larry burns Dec 22 '18 at 22:07
  • @larryburns Because "takes precedence" doesn't refer to order, as in "is hoisted above the other". Declarations don't really have any order for our purposes, all variables are created at once (*that*'s what "hoisting" actually means). The precedence refers to the value that the variable is initialised with, `undefined` for `var`s and function objects for `function`s. The rule means that when there is a `function` declaration with the same name as a `var` declaration, then the variable is initialised as a function. – Bergi Dec 22 '18 at 22:31

3 Answers3

4

(From the comments)

If variable assignment takes precedence over function declaration why isn't double = 22 above the function declaration?

Variable name declarations are hoisted, but assignments (=) are never hoisted.

Then what does "Variable assignment takes precedence over function declaration" mean?

It makes no sense at all, really. An assignment and a declaration are two totally unrelated things, they don't "take precedence" over each other. I guess it's supposed to mean just that you can always assign a mutable variable, and it will hold the assigned value afterwards, regardless of where/how the variable was declared (with var or function).

How in my last example even though function is hoisted above the variable declaration the output is still function instead of undefined?

Because "takes precedence" doesn't refer to order, as in "is hoisted above the other". Declarations don't really have any order for our purposes, all variables are created at once (that's what "hoisting" actually means).

The precedence refers to the value that the variable is initialised with, undefined for vars and function objects for functions. The rule means that when there is a function declaration with the same name as a var declaration, then the variable is initialised with the function.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
0

This should clarify what is meant:

var myVar = 1;

outerFunc1();
outerFunc2();


function outerFunc1()
{

  innerFunc();    // works due to hoisted declaration

  function innerFunc()
  {
    console.log(myVar);
  }

  var innerFunc;  // function declarations take precedence

  innerFunc();    // works even if var innerFunc is declared
}

function outerFunc2()
{

  innerFunc();    // outputs undefined since myVar is redeclared locally (hoisted)

  function innerFunc()
  {
    console.log(myVar);
  }

  var myVar = 2;  // local declaration (AND initialisation)


  var innerFunc;  // function declaration take precedence

  innerFunc();    // outputs 2 even if var innerFunc is declared

  innerFunc = 1;  // this overwrites the function
  innerFunc();    // gives an error 'not a function'.
}
Pinke Helga
  • 6,378
  • 2
  • 22
  • 42
  • It's unclear what you mean by "*redeclared locally*". – Bergi Dec 22 '18 at 22:33
  • @Bergi What don't you understand? `var myVar` is declared in global scope and redeclared in function scope as a local variable. – Pinke Helga Dec 22 '18 at 22:36
  • Oh, you meant that it's declared in `outerFunc2`, not in the `innerFunc` that is getting called in the line with the comment. – Bergi Dec 22 '18 at 22:39
-1

As per MDN: https://developer.mozilla.org/en-US/docs/Glossary/Hoisting#Only_declarations_are_hoisted

JavaScript only hoists declarations, not initializations.

So let's rewrite your examples for a better understanding:

1.

var double = 22

function double(num) {
  return (num*2)
}

console.log(typeof double)

This can be read like:

// hoisted
var double

function double(num) {
  return (num*2)
}

// initialise
double = 22

console.log(typeof double)

2 & 3 Can be read exactly in the order as you have written them. In 2) the initialisation happens last, so it outputs Number. In 3) there is no initialisation at all, so the function is declared last, so it outputs Function.

So your confusion about the third example seems to be understanding the difference between declarations and initialisations.


EDIT: There is definitely some confusion with ordering (hence writing this can be read like..). While javascript technically hoists the functions first, you should still read your code as I have written, as functions take priority over the variable declarations. In other words, while technically the hoisting goes:

function double(num) {
  return (num*2);
}    

var double;    

console.log(typeof double); // Output: function

The function still takes priority, so it is better to read the other way around.

Matt Way
  • 32,319
  • 10
  • 79
  • 85
  • Function declarations are hoisted above variable declarations. There is no initialization in my last example. If the last double type is a variable in the document it should log as undefined, but it logs as a function. – larry burns Dec 22 '18 at 22:31
  • Updated my answer. – Matt Way Dec 22 '18 at 22:52