Table of Contents

About

Variable scope in Javascript.

variable scope is delimited by the function definition, not a the block level

A block has the scope of its inner function.

As a function is also an object, by generalization, the scope is at the object level.

The keyword this gives access to this scope object.

There is an exception to the function ruling scope and this is with a caught exception variable in a try…catch block. This variable is scoped only to the try..catch block. See Javascript - Exception

Lexical environment / Scope chain

In the ES5 specification, the scope diagram is called the lexical environment (or scope chain in older versions of the standard).

Javascript looks the variables:

  • first down in the prototype chain
  • then up in the scope, starting with the innermost scope and working its way outward.

Example: for the below code,

function pointsOnCircle(n){
    var point = new Point(x,y);
    ...
}

the scope diagram can be represented as;

Javascript Lexical Environment Scope Chaine

where:

Scope and

Block

The scope is not at the block level.

Meaning that the variable declared in the for loop (a block) exists also outside the loop. If you want to restraint the scope of a variable, you need to create it inside a function.

Variable

A variable declared in a script without function is declared in the global namespace which is the top variable context space.

Declaring a variable anywhere in a block code (or script) is equivalent to declaring it at the top of its scope (or script). See hoisting

Hoisting

Declaring a variable anywhere in a block code (or script) is equivalent to declaring it at the top of its scope (or script)

Variable declarations are hoisted up to the top of the context (script, function,…) in which they reside.

hoisting means moving the var declaration to the top of its enclosing scope. Technically, this process is explained by how code is compiled,

foo = 2
var foo;

is treated as:

var foo;
foo = 2

Example:

function noHoisting(){
    bar = "global variable declaration because without the var keyword in a function";
}
// Run the function to run the variable declaration
noHoisting();
console.log(bar);

function hoisting(){
    bar = "local variable declaration because declared below with the var keyword";
    // thanks to variable hoisting the below statement will placed at the top of its scope (ie the actual function)
    // and the variable will not be considered global anymore but local
    var bar; 
    console.log(bar);
}
hoisting();
console.log(bar);

Management

Creation

IIFE

To force the creation of a local scope, a nested function must be created and called right away. This technique is known as the immediately invoked function expression, or IIFE and is an indispensable workaround for JavaScript’s lack of block scoping.

Example:

(function IIFE(){
    var foo = "IFFE variable";
    console.log( "Hello!" ); 
})(); // "Hello!"

// foo is not defined in the global scope
if (typeof foo == 'undefined') {
   console.log("foo is undefined");
}

Modification

Statement

Two statements can modify the actual lexical scope:

Restriction

An IIFE is often used to create a scope in order to declare variables that won’t affect the surrounding code outside of it. See IIFE

Webtool (Chrome)

Chrome Developer Tool:

Chrome Dev Tool Source Debugger Scope

Example

var x = 0; // x is a global variable created then in the global namespace.
var y = 1;

console.log("The global variable x has been declared with the value "+x+"."); 
console.log("The global variable y has been declared with the value "+y+"."); 

function f(){
  
  var x = 1; // x is declared locally in the function. There is the two x variables: The first one global and the second one local 
  x = 2; // This modification will not impact the global variable
  console.log("The local variable x has the value "+x);
  
  y = 2; // This modification will impact the global variable because z is not declare with the var symbol.
  
  z = x; // z is NOT declared locally with the var keyword. z will then leak outside of the function
  

}
f(); // Execute function f

console.log("The global variable x has still the value "+x+", the function got no impact on it"); // 0
console.log("The global variable y has the value "+y+", it has been changed in the function because it was not declared locally with the var keyword"); 
console.log("The variable z has the value "+z+", has leaked from the function because it was not declared with the var keyword it has a global scope"); 

Documentation / Reference