First, let's go over the different scope resolutions in JavaScript.
JavaScript uses scope chains to establish the scope of variables. When resolving a variable, it starts at the innermost scope and searches outwards.
Variables, functions, and objects defined at this level are available to any code in the entire program. This is the outermost scope.
var x = 'hi'; function a() { console.log(x); } a(); // 'hi'
Each function described has its own local scope. Any function defined within another function has a nested local scope that is linked to the outer function. Almost always, it's the position in the source that defines the scope.
var x = 'hi'; function a() { console.log(x); } function b() { var x = 'hello'; console.log(x); } b(); // hello a(); // hi
Local scope is only for functions and not for any expression statements (if
, for
, while
, and so on), which is different from how most languages treat scope.
function c() { var y = 'greetings'; if (true) { var y = 'guten tag'; } console.log(y); } function d() { var y = 'greetings'; function e() { var y = 'guten tag'; } console.log(y) } c(); // 'guten tag' d(); // 'greetings'
In functional programming, this isn't as much of a concern because functions are used more often and expression statements less often. For example:
function e(){ var z = 'namaste'; [1,2,3].foreach(function(n) { var z = 'aloha'; } isTrue(function(){ var z = 'good morning'; }); console.log(z); } e(); // 'namaste'
Object properties have their own scope chains as well.
var x = 'hi'; var obj = function(){ this.x = 'hola'; }; var foo = new obj(); console.log(foo.x); // 'hola' foo.x = 'bonjour'; console.log(foo.x); // 'bonjour'
The object's prototype is further down the scope chain.
obj.prototype.x = 'greetings'; obj.prototype.y = 'konnichi ha'; var bar = new obj(); console.log(bar.x); // still prints 'hola' console.log(bar.y); // 'konnichi ha'
This isn't even close to being comprehensive, but these three types of scope are enough to get started.