JavaScript Scope & Closures

One of the biggest challenges facing new JavaScript (JS) developers is the global nature of JS. Unlike other languages, almost everything in JS is global. Scope in computer programming, in simplest terms, is the extend of a properties visibility throughout the code. Many popular programming languages have block scope, meaning that you can enclose code within curly braces and hide it from other code. Take a look at the code block below:

var aGlobalProperty = "I'm global!";

{
     var aBlockScopedProperty = "I'm block scoped!";
}

console.log("aGlobalProperty" + aGlobalProperty);
console.log("aBlockScopedProperty" + aBlockScopedProperty);
// I'm global!
// I'm block scoped!

/*If JS had block scope, this would result in 'undefined' 
  for our aBlockScopedProperty since it should have existed
  only within our brackets above.

  Unfortunately JavaScript does not provide blockscope, and 
  consequently, it can be difficult to organize code in a
  manner that does not allow for easy access and manipulation 
  of properties. Thankfully, JS does provide functional scope. 
  Properties created within a function are private to that 
  function and its descendants. */

var aClosureFunction = function() {
     var aFunctionalScopedProperty = "I'm functionally scoped!";
     console.log(aFunctionalScopedProperty);
     // I'm functionally scoped!
};

/* Here our property has printed out as normal since it has access to it
   from within the function. */

  If I tried to do any of the calls commented out below, I would get
  either a TypeError undefined or a ReferenceError since the property
  isn't visible from outside the function. (note that there is more
  wrong with the commented out log statements than just the scope) */

//console.log("outside function: " + aFunctionalScopedProperty);
//console.log("or from function: " + aClosureFunction.aFunctionalScopedProperty);

Functional scope does allow us to do some clever tricks to help encapsulate our properties and protect them from outside meddling and colliding property names.  Lets take a look at a few types of the common closures.

var aGlobalVariable = "I'm global!";
function myGetterFunction() {
   var notGlobal = "I'm not global!";
   return function() {
     return notGlobal;
   }(); // self executing
};

/* Now if I were to try to access 'notGlobal'
   from outside the function, I'd get an error.
   However, I can still access it by executing
   the myGetterFunction function and setting
   the result to another function */

var firstAccess = myGetterFunction();

console.log( firstAccess ); // I'm not global!

/* The resulting function now gives the rest of
   our application access to the value of notGlobal in
   our myGetterFunction.

   Lets take this idea one step further and allow
   the properties to be modified via global getter and
   setter functions */

var getVar;
var setVar;
(function() {
   var notGlobal = "I'm a different not global property!";
   getVar = function(){
      return notGlobal;
   }
   setVar = function(value) {
      notGlobal = value;
   }
})();

console.log( getVar() );
// I'm a different not global property!

setVar("You've changed me.");
console.log( getVar() );
// You've changed me.

/* Our closure is complete because our global functions getVar
   and setVar still keep access to the anonymous self-executing
   functions notGlobal variable. We are able
   to update and modify it at will with our getVar() and setVar()
   functions that were passed back in returned object map.

   We're able to do this bit of cleverness due to
   JavaScript's awesome, and sometimes frustrating, ability
   to treat nearly everything as a transferable piece of
   data - even functions! */

console.log( firstAccess );
// I'm not global!

/*  */

Also notice that even though both ‘myGetterFunction’ and the getVar/setVar functions both have properties named ‘notGlobal’ they are both unique. We have prevented them from being global through the use of our functional scope closures.

Now lets take it one step further and create a utility class that creates new string generating functions.

function addSurname(surname) {
	var name = surname; // this actually isn't necessary as we'll see later
	return function( firstname ) {
		return firstname + " " + surname;
	}
}

var makeLannister = addSurname("Lannister");
var makeStark = addSurname("Stark");

var theQueen = makeLannister("Cersei");
var theImp = makeLannister("Tyrion");

var theHand = makeStark("Eddard");
var makeBestCharacter = makeStark("Arya");

console.log('The Queen: ' + theQueen);
// The Queen: Cersei Lannister
console.log('The Imp: ' + theImp);
// The Imp: Tyrion Lannister
console.log('The Hand: ' + theHand);
// The Hand: Eddard Stark
console.log('The Best Character: ' + makeBestCharacter);
// The Best Character: Arya Stark

Neato! You should now be getting a better feel for how closures can help simplify your code and protect your properties from meddling. Unless our new function ‘makeLannister’ gets overridden, we never have to worry about it’s hidden ‘name’ property being changed.

Lets take a look at one final practical example where we use closures to help extend objects.

function makeWarrior( name, weapon, armor) {
	var life = 100;
	function _fight() {
		return (name + ' swings his ' + weapon );
	}

	function _defend() {
		life = life - 25;
		return (name + ' takes a hit on his ' + armor);
	}

	function _getLife() {
		if( life > 0 ) {
			return (name + ' has ' + life + ' points.');
		} else {
			return (name + ' is dead.  So sad.');
		}
	}

	return { fight:_fight, defend:_defend, getLife:_getLife }
}

var sandorClegane = makeWarrior('The Hound', 'great sword', 'heavy armor');
sandorClegane.fight();

var bronn = makeWarrior('Bronn', 'sword and dagger', 'light armor');
bronn.fight();

console.log( sandorClegane.fight() );
// The Hound swings his great sword
console.log( bronn.defend() );
// Bronn takes a hit on his light armor
console.log( bronn.defend() );
// Bronn takes a hit on his light armor
console.log( bronn.getLife() );
// Bronn has 50 points.
console.log( bronn.defend() );
// Bronn takes a hit on his light armor
console.log( bronn.defend() );
// Bronn takes a hit on his light armor 
console.log( bronn.getLife() );
// Bronn is dead.  So sad.

/* Lets make a new warlock that uses
   closures to extend our warrior function */

function makeWarlock( name, type, weapon ) {
	var uber = makeWarrior(name, weapon, 'mage robes');
	_defend = uber.defend;
	_uberFight = uber.fight;

	uber.fight = function() {
		return (name + ' uses his ' + weapon + ' to avoid fighting directly.');
	}

	function _castSpell() {
		return (name + ' casts an ' + type + "'s spell");
	}

	return { castSpell:_castSpell, fight:uber.fight, defend:_defend, uberFight:_uberFight};
}

var pyatPree = makeWarlock('Pyat Pree', 'illusionist', 'cunning');
console.log( pyatPree.castSpell() );
// Pyat Pree casts an illusionist's spell
console.log( pyatPree.fight() );
// Pyat Pree uses his cunning to avoid fighting directly.
console.log( pyatPree.defend() );
// Pyat Pree takes a hit on his mage robes
console.log( pyatPree.uberFight() );
// Pyat Pree swings his cunning

Through the use of our ‘uber’ object that keeps a reference to our original warrior object we can continue to access its properties in their original form.  We assigned our original warrior’s fight function to _uberFight BEFORE we overrided it with our own fight function. This is a bit convoluted, but it demonstrates how REFERENCES are passed around. Had I created our new uber.fight function BEFORE assigning uber.fight to _uberFight, they would both print out the same message.

We aren’t designating any new properties to store the passed in arguments used by our warrior or warlock functions.  This works because we are passing in primitive string objects.  If our functions were to take objects, the passing by reference of object may cause problems if those objects were modified outside of our function.

I hope this helps clarify closures!