6

I was reading about hoisting in mozilla, and noticed an example explaining how a variable can leak outside of the function scope: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var#Initialization_of_several_variables

The example says,

var x = 0;

function f(){
  var x = y = 1; // x is declared locally. y is not!
}
f();

console.log(x, y); // 0, 1
// x is the global one as expected
// y leaked outside of the function, though! 

I don't understand what is happening here. I am looking for a technical explanation more than anything. How is y accessible outside at this point?

Edit: I understand how this function is behaving, and I should clarify and say I wanted an understanding of what is happening in the code and memory (ex, pointers, etc..).

Strawberry
  • 66,024
  • 56
  • 149
  • 197
  • 4
    Because it isn't prefixed with `var`. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var - *"Assigning a value to an undeclared variable implicitly creates it as a global variable "* – Phil Jan 23 '15 at 03:48

4 Answers4

4

This is breakdown of the statement:

   var x = y = 1;
   \___/   \____/
identifier initializer 
   \____________/
  variable declaration

In this case the initializer is another assignment. Due to variable hoisting, this statement is evaluated as follows:

var x;
x = y = 1;

As you can see, y is not declared. Assigning to an undeclared variable creates a global variable (implicitly).

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
3

you have var x = y = 1 which means that x is declared inside but y is not, var doesn't apply to y in this case, that's why it's leaked outside the function

Soufiane Hassou
  • 17,257
  • 2
  • 39
  • 75
2
var x = 0;

function f(){
  var y = 1; 
  var x = 1; 
}
f();

console.log(x, y); 

Try the above code. The problem is that you didn't include a var in front of y. The result is that y is hoisted into global scope.

TGH
  • 38,769
  • 12
  • 102
  • 135
1

In JavaScript, variables are declared as soon as you use them, like this:

function f(){
  y = 1;
}

The problem is that y is not scoped within f(), like it would be in most other programming languages. So you can do something like this:

function f(){
  y = 1;
}

console.log(y);

And you will see 1 on the console.

This is generally considered a bad practice, because it pollutes your namespace and can lead to subtle, hard to track down bugs.

To avoid this, always use let or var to explicitly declare variables, like this:

function f(){
  let y = 1;
}

// the y declared in f() is not accessible out here
console.log(y)

This should give you an error like: "Uncaught ReferenceError: y is not defined" on your console.

For more details, read this page, specifically the section 'Automatically Global': http://www.w3schools.com/js/js_scope.asp

In the example you gave above the problem is more subtle, because x is scoped properly, but the short-hand declaration of y makes it globally scoped:

function f(){
  let x = y = 1;
}

EDIT 2022: Updated to recommend let over var. Here is an explanation of the difference.

JBCP
  • 13,109
  • 9
  • 73
  • 111