1

I'm new to JavaScript and am trying to understand the concepts of hoisting and scope.

Case 1

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);

and I have the following output in the console

Auro 1
Auro 2

If I understand hoisting correctly, JS engine hoists the declaration of a variable first and then automatically assigns a value undefined to it. Only when it encounters the assignment (=) operator, does it actually assign the intended value to it.

If my understanding above is correct, then the first time the logName function was called, the variable name should have printed undefined, but it is printing the value.

Case 2

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";

Output in the console:

Baner 1
Auro 2

This confuses me even more. Here the first call to the function logName picked the later assignment to the variable and printed Baner, however, the second call picked the previous assignment, that is Auro.

What is going on here? What am I missing?

Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
Auro
  • 1,578
  • 3
  • 31
  • 62

3 Answers3

5

In the global scope, name refers to window.name, that is the name property of the window - which in the examples you gave are sif1 and sif2 (possibly "Snippet IFrame 1/2").

Since window.name already exists, var name; in the global scope does nothing. The variable is already defined.

Until you overwrite it - and note that again you are setting the global window.name property. And, depending on browser settings, this can persist across reloads of the page (since you're naming the entire window). This explains why you see the value "stick".

Niet the Dark Absol
  • 320,036
  • 81
  • 464
  • 592
  • Nice call out on the iframe names. When I updated the question to make them snippets, that threw me for a loop, ^_^ – Taplar May 29 '19 at 17:26
  • If you press blue 'Run...' button twice then browser will open new tab in your compuer too - or it works like that only in my local browser? – Kamil Kiełczewski May 29 '19 at 17:27
  • 1
    @KamilKiełczewski That would be because, having renamed `window.name`, the "Run" button can no longer find a frame with the desired name and so a new window/tab is opened - with that name. – Niet the Dark Absol May 29 '19 at 17:28
0

As addition to other answers I can say, that just not use var but use ES6 let or const instead and 'surprising behaviour' will disappear.

let name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345
0

No none of the specified output matches, as initially you have value of name equal to window.name, so initially the value of name variable will be equal to winow.name and once overwrite it you get the new value

let's understand how this all works

You can understand as such there are two phase of code execution

  1. Creation phase
  2. Execution phase

Creation phase:- During creation phase function is hoisted at top as it is, while the variable are hoisted but there is no value assigned to it ( or you can say it's value is undefined )

Execution phase:- During execution context it assigns value to variable when it reaches line where assignment is happening

var name;

function logName(num) {
  console.log(name, num);
}

logName(1);
name = "Auro";
logName(2);
name = "Baner";
Code Maniac
  • 37,143
  • 5
  • 39
  • 60