Advanced JavaScript: Namespaces, Closures, Self-Invoking Functions, and much, much more…

In the past year that I’ve been working at Yahoo! I’ve found myself more in the role of UI Developer in web application development.

This involves developing the client-side display, the client behaviors, request and response handling with server-based actions which may interface with a series of back-end or 3rd party services. HTML and CSS are used for content mark-up and styling. JavaScript is used for manipulating the client data and display based on user interaction. AJAX is leveraged heavily to interact with services. A Java based action layer sits on the server and acts as the controller for request dispatching, and interfacing with various services.

Given JavaScript’s heavy usage in this structure, I’ve learned a lot about JS limitations and powers. For years I generally avoided doing any kind of development that relied heavily on JavaScript. It’s implementation across browsers was disparate, and errors were impossible to debug. Things have obviously improved drastically in the past few years.

An increased usage and reliance on JavaScript means it’s very important to write “enterprise-level” code in a language that doesn’t always assist you the way Java or Python do in this task. One of the things I’ve always disliked about JS is its confusing variable scoping.

This article will cover a series of concepts in advanced JS usage which can help developers avoid problems caused by poor scoping. These concepts include:

- Namespacing
– Self-Invoking functions
– Closures

First, let’s cover the concept of namespacing in JavaScript. Normally, you can define variables in JavaScript in two different methods:

myFirstVar = "some value";

var mySecondVar = "some other value";

In the case of myFirstVar, this is a global variable, no matter where you define this it will be available to all other JavaScript code in the page/screen where it occurs. Using this method to declare variables is extremely messy. With large applications you can easily eat up a lot of memory if you’re declaring global variables all over the place. Also, there’s a strong chance that during the execution of your code, you will encounter a collision where the same variable is getting used for different intended uses.

The second case: mySecondVar uses the “var” keyword to limit the scope to the current executing block of code, and all blocks of code within the current one. If mySecondVar was inside of a function or a conditional block, then it would be local to those blocks of code. In the case above, it’s essentially another global variable.

To avoid polluting the global scope, we’ll use an object structure with a semantic naming pattern to store all code that we need available on a global scope, but we’ll run much less risk of code collision and we’ll have a smaller memory footprint.

Let’s pretend we’re writing code for dgmlive.com. We’ll create a global JS object called DGM:

var DGM = {};

We can add functionality as children to this object. We could for instance create a series of objects that correspond to data entities that we use in dgmlive.com, and those objects would contain data and behavior specific to those entities. Examples include:

- DGM.Artist
– DGM.Recording
– DGM.util.DownloadConfirm
– DGM.widget.MediaPlayer

Now, we’re still going to have situations where we’ll want to declare variables that don’t naturally fit into a namespaced object structure. But we don’t want those variables to have a global scope. This is where self-invoking functions come in.

Normally in JavaScript, you define a function at some point in your script, and later invoke it. With a self-invoking function, it’s executed when the definition is parsed by the browser / client. Variables declared inside of a self-invoking function using the “var” keyword only have a scope local to that self-invoking function. Here’s what a self-invoking function looks like:

(function() {
    // All your JS code goes in here
})();

A functional example:

(function() {
    var myThirdVar = "Try to get at this outside this function";
})();

alert(myThirdVar); // undefined

Let’s take these concepts further and incorporate some object oriented programming principles to our JavaScript code that aren’t explicitly provided for with basic JavaScript.

Let’s build a basic version of the proposed DGM.Artist object. Here’s the code:

var DGM = {}; // only global property, the root of our namespace

(function () { // Self-invoking function

/**
* Creates a new artist object
*
* @param Object an initial configuration for this artist
* @constructor
*/
DGM.Artist = function(
/* Obj */		oConfig
) {

    // Define private members
    var _name = oConfig.name;
    var _givenName = "";
    var _surName = "";

    // Private logic method
    // A not-so-good way of getting first and last name from a single name
    var _splitName = function(name) {
        var names = name.split(" ");
        _givenName = names[0];
        _surName = names[1];
    };

        return { // publicly accessible API

            getName : function() {
                return _name;
            },

            setName : function(newName) {
                _splitName(newName);
                _name = newName;
            },

            getGivenName : function() {
                return _givenName;
            },

            getSurName : function() {
                return _surName;
            }

        };

    };

    var robertFrippConfig = {
        name : "Robert Fripp"
    };

    var newArtist = new DGM.Artist(robertFrippConfig);

    alert(newArtist.getName());
    alert(name);
    alert(givenName);

    newArtist.setName("Bobby Willcox");
    alert(newArtist.getName());
    alert(newArtist.name);
})();

Ok, there’s a lot there. Let’s walk through it a little at a time:

var DGM = {};

That’s the start of our namespace object. We’ll add children to it and avoid polluting the global namespace.

We then start a self-invoking function:

(function () {

It’s not really necessary to wrap the declaration of DGM.Artist in a self-invoking function, since this is just going to have the same scope as DGM, but it’s a nice touch. We do need the self-invoking function to contain the instantiation of DGM.Artist.

We declare DGM.Artist as a function, but we’re going to use it as an object constructor. It returns an object with a specific sub-set of functions that we want to make publicly accessible.

	DGM.Artist = function(
		/* Obj */		oConfig
	) {

        ...

        return { ... };

We create an instance of DGM.Artist using the new statement:

var newArtist = new DGM.Artist(robertFrippConfig);

Now let’s look closer at DGM.Artist. JavaScript doesn’t support different traditional OO member accessibility (i.e. public, protected, private). But we can use the “var” keyword and JS scoping to our advantage in this instance.

Variables declared with “var” inside of DGM.Artist constructor method are local to that method, and not accessible to JS outside of the method. However, the variables themselves persist inside each instance of that object. So, we can use traditional accessor methods (getters/setters) to manipulate those variables from outside. This behavior is called a closure.

This gives the programmer some power over how an object’s properties are manipulated during run-time. However, this shouldn’t be construed as any type of security measure to protect sensitive data.

So, getting back to the example, we set up a series of private variables which will contain data for each instance of DGM.Artist that we create:

                // Define private members
		var _name = oConfig.name;
		var _givenName = "";
		var _surName = "";

I’ve used the convention of putting an underscore in front of the member names. This does nothing other than visually indicate to the programmer that these are intended as private variables.

In the return block of the constructor method, I build an object which has a series of methods which can be used to manipulate these private variables after the instance is created:

return { // publicly accessible API

			getName : function() {
				return _name;
			},

			setName : function(newName) {
				_splitName(newName);
				_name = newName;
			},

			getGivenName : function() {
				return _givenName;
			}, 

			getSurName : function() {
				return _surName;
			}

		};

Take a look for a moment at the setName() method. This is used in the instance to change the name of the artist if necessary. Inside of setName() we call a private method _splitNames() defined in DGM.Artist constructor, which takes our name string and splits it into a given and a surname.

===

I hope this gives you some sense of how to avoid scoping problems in your JavaScript development, and also gives you some sense of how to use closures and object-oriented JavaScript to unleash some of the power that JavaScript has available.

About these ads

16 responses to “Advanced JavaScript: Namespaces, Closures, Self-Invoking Functions, and much, much more…

  1. Greg Salisbury

    Eric,sorry I put Hi Chris on my post – the name must have caught my eye subconciously, as it’s at the bottom of your page.
    All the best.

  2. Greg Salisbury

    Maybe it will post this time, and with your name correct too ;-)…

    Hi Eric. Good article. I think javascript programmers are generally getting there/here, though the Prototype library uses/used a bunch of globals, at one point.

    I’m hoping you’re an expert on scope too? Is it possible to redefine a func, and keep it’s original scope…

    glob= {};
    (function(){
    var v= 5
    glob.f= function(){ alert(v) }
    })()
    glob.f() // alerts 5
    glob.f=function(){ alert(v) }
    glob.f(); // error – as v is undefined (not in original scope?)

    Any ideas? I’ll owe you one ;-)
    All the best.

  3. Greg Salisbury

    Doesn’t seem to want to accept my original post, possibly why you not have any.

    All the best

  4. Greg Salisbury

    It’s not accepting my posts.

  5. Greg,

    Sorry. I just saw your first comment buried in the wordpress spam queue.

    Better late than never on this one.

    For the example you give the v variable’s scope only exists inside of the self-invoking function, so the redefined glob.f() cannot access it.

    So, either v needs to be redefined along with the glob.f() method, or the redefinition should take place in the same self-invoking function code block.

    Adding v to an object namespace that is already global, like glob.v, would also work.

    I hope this helps,

    Eric

  6. Hi Eric,
    interesting post.

    I am quite new to JS. May I seek for your advice how to do JS namespace in below case:
    I have 2 JS files with exact variable name, function name. I want to load them in one html page, each will help provide ajax suggest for one single textbox. How can I do JS namespace without modifying JS files itself.
    Thanks and best regards,

    • Steve,

      In order to get around the problem you describe you’re going to have to edit the JavaScript to create a global object that serves as a namespace (as described in the article).

      Feel free to post the code examples and perhaps I can help you further.

      Eric

      • Dima Polovinkin

        When I created two identical .js files having same ‘var someVariable’ then these names conflicted. After embracing both js files with with
        (function(){
        //put the whole js code here
        })()
        I had no problems with them. Maybe this may help you.

  7. good to find this blog, good timing for I was searching for the \”self-invoking functions\” been reading alot about Javascript OOP..

    http://kaixersoft.wordpress.com

  8. Hey Eric, This was very helpful to me as I am reworking a piece of code to use a global namespace for the reasons you’ve already alluded to above. Thanks so much for the post.

  9. I have found it’s useful to adopt the convention of a preceding semicolon, this eliminates a common error (where there are preceding braces without a semicolon). Otherwise you get mysterious behaviours when the brackets and braces are combined by the interpreter…

    ;(function() {
    var myThirdVar = “Try to get at this outside this function”;
    })();

  10. I found a much easier and probably more scalable solution online. Although the method above is sound. This one gives you true closure and “OOP” style namespacing though. I suppose it’s each to their own though aye? Here is the link Read

  11. Pingback: Clean Code: Reducing WTFs Per Minute | 42 Lines

  12. Pingback: My Daily Shared Bookmarksfboiton's blog | fboiton's blog

  13. am i the only getting an error _givenName undefined?

  14. What’s up i am kavin, its my first time to commenting anywhere, when i read
    this paragraph i thought i could also create comment due to this brilliant piece of writing.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s