Fundamental Javascript: Controlling function and variable scope


Your Javascript will be deployed alongside scripts from other developers. Lets assume that those developers are neither as talented at writing Javascript, nor as conscientious as you are; they use generic function and variable names in the global scope. These Javascript developers just don’t mind if they play chaos with your carefully crafted script.

With a little extra knowledge, your carefully crafted Javascript can remain unsullied by the careless developer. Learn to limit and manage the scope and exposure of your variables and functions.

Learning this pattern will make you a good citizen amongst your peers, it will reduce the number of mystifying bugs you encounter and will guarantee your code will work long in to the future.

The basic pattern

It’s possible to create a function that will encapsulate your Javascript code. Variables and functions defined within the encapsulating function will be private to the function, avoiding naming clashes with any other Javascript.

This code pattern is simple:

(function () {
// Your code here
}());

This is an immediately-invoked function expression. The terminology is a little opaque, but it’s a simple enough concept. Visit the link for the full run-down, or accept that this function will be executed as it is encountered.

Javascript variable and function scope operates at function level. Variables and functions declared inside a function remain private to that function. Undeclared variables are assigned to the global scope. This pattern gives us an enclosing function; we can move away from the global scope.

Take the following example:

(function () {
  var variable1;

  variable1 = "variable1 text";
  variable2 = "variable2 text"; // variable hasn’t been declared!

  console.log(variable1); // variable1 text
  console.log(variable2); // variable2 text
}());

console.log(variable2); // variable2 text
console.log(variable1); // error

‘variable1′ is declared and can only be accessed inside the function. ‘variable2′ is not declared, is therefore a global variable and is available outside the function – consequently its value can be changed inadvertently be other code using the same variable name.

This code pattern is very useful; it prevents other Javascript code from inadvertently modifying your variables and functions at runtime. However, it does have a downside – you now can’t access these functions and variables from anywhere outside of the function. You may need to operate in conjunction with another Javascript file, or Javascript placed in HTML source code.

Expose yourself

We need a way to expose those variables and functions that require exposing. Consider the following:

(function () {
var variable1;
variable1 = "variable1 text";

function function1 () {
return(variable1);
};

console.log(variable1);     // variable1 text
console.log( function1() ); // variable1 text
}());

console.log(variable1);   // error
console.log(function1()); // error

Neither ‘variable1′ nor ‘function1′ are available outside the function. To overcome this issue we can create one global variable, using this global variable to namespace any functions or variables we wish to expose.

var mynamespace = (function () {
   var exposed = {}; // We’ll assign our exposed variables and functions with the exposed array, and return it from our function.

   exposed.variable1 = "variable1 text";
   exposed.function1 = function () {
     return(variable1);
   };

var variable1 = "variable1 text";

function function1 () {
     return(variable1);
   };

   console.log(exposed.variable1);   // variable1 text
   console.log(variable1);           // variable1 text
   console.log(function1());         // variable1 text
   console.log(exposed.function1()); // variable1 text

return exposed;
}());

console.log(mynamespace.variable1);    // variable1 text
console.log(mynamespace.function1());  // variable1 text
console.log(variable1);                // error
console.log(function1());              // error

Here we create a ‘mynamespace’ global variable to which we assign our anonymous function. The return value of the anonymous function will be an array of variable and function references.

Inside our anonymous function we create an array called ‘exposed’. This is where we will collect our variable and function references. We use the ‘exposed’ array as our return value for the function.

To create private variables and functions we simply need to declare them as usual (see ‘variable1′ and ‘function1′).

To expose them outside our function we must assign them to our ‘exposed’ array. ‘exposed.variable1 = …’ and ‘exposed.function1 = …’ demonstrate this principle.

Within the anonymous function we can access these using ‘exposed.{whatever}’ , outside the function we can access these using ‘mynamespace.{whatever}’.

Tidy

To finish up, here’s a tidied version of the pattern:

var mynamespace = (function () {
  var exposed = {};

  // Private variable
var variable1 = "variable1 text";
  // Exposed variable
  exposed.variable1 = "variable1 text";

  // Private function
  function function1 () {
    return(variable1);
  };

  // Exposed function
  exposed.function1 = function () {
    return(variable1);
  };

return exposed;
}());
Tagged
Follow

Get every new post delivered to your Inbox.