Modern JavaScript Techniques
April 21st, 2009In my interview with The Thirsty Developer podcast I mentioned some modern JavaScript techniques. It is hard to explain these techniques in a podcast so I wanted to post them here.
The biggest problem area I work to avoid when working with JavaScript is the scoping issue. It has been very common to simply create a series of functions and call them however you see fit from event handlers in your HTML. This was all fine when you had 300 lines of JavaScript for your entire site because it was just used for a slight site enhancement. Now if you are building a much more complex site with lots of interaction, you will have several thousand lines of code. Every one of these functions and variables that you define are all placed in the global scope, which is the window object. Consider the following code.
This code is equivalent to the following code, assuming this code is in the global scope and not within a function block.
Why is this useful? Well, if you are within a function block and declare a variable the scope of that variable is limited to that function block. If you want to declare a variable and put it into the global scope you can use the window object in this way to do so. (Hint: window is the container for the global scope.)
But you do not want to dirty up the global scope which will lead to naming conflicts and code that is very difficult to maintain. What you may want is namespacing so that you can isolate blocks of code in an organized structure. There is no language feature in JavaScript for namespaces like you find in C# or VB.NET but you can put references into objects. The following code declares a variable which is an object that holds onto properties.
This is one way that you can manage scope, but when you start to have a fuller hierarchy you can imagine that this would become difficult to manage. So you can leverage the Module Pattern where you declare everything without regard for scope and then wrap it in what is now being called a module.
The first and last lines are a little hard to understand when you see it for the first time. Think of it like algebra. When you want to manage scope in an expression you use parentheses. This way you can make an expression like (4 + 2) * 3 to ensure that the 4 and 2 are added before the result is multiplied by 3. The same premise works here with the Module Pattern. What happens outside the parentheses does not affect what is inside. Then the first thing in the container is an anonymous function, but notice when the function block is closed there is a set of parentheses which causes the function to be executed immediately. The code in the function block is executed immediately and then contained with the scope of that function block. In the case of this code snippet nothing is happening because the code is not doing anything. How is this useful?
In the code below we will reference a little jQuery code to attach an event handler function. This code will find all anchor tags on the page which have Close as a class value and attach a click event. This click event will hide the parent container of the anchor element.
This code is isolated and executed, leaving nothing in the global scope while the function that is attached to any matching anchor tags is still accessible because the element is now bound to the function as a click event handler.
Now you may want to start organizing this nicely scoped code into namespaces and you can do so by declaring your variables and functions within the module and export them to through a global variable, as shown in the code below.
Now you can do whatever you like within your module and export the public portions you choose. In this case I added the reference for the function to a container named SST. I can now access it anywhere in my code. The key difference here is that now all my code for this site will be held within the SST container and I will not have to be concerned with using third party libraries which may place variables into the global scope. Most libraries, like jQuery, will declare the minimal amount of variables in the global scope. The jQuery library uses $ and jQuery for the global scope and then functions, variables and plugins used by jQuery are held under that scope. The same is true for libraries like the Yahoo UI library which uses YUI in the global scope.
As you write more code and need to organize it further you will want to have multiple levels in your namespace hierarchy. You can easily chain containers together, such as the following code.
When you have a lot of code you will want to split it across multiple files, so declaring your namespace hierarchy from a central point may not be ideal, so you will want to use a function that will build your structure in a simple way.
Not every page will use every script and if you have 500kb of script you want to use the minimal amount of code on each page, so I find it best to ensure the namespace that I am defining in this module is defined within the module.
Now I have my functions and variables defined in an isolated scope where the functions can access these variables, which are now effectively private variables, and the public functions are exposed through the namespace structure.
Since I use these techniques often I have created a core library that I have been using for many projects this past year. I call it core.js and it includes the CreateNamespace function that I referenced in the code snippets above. And if you are using Visual Studio, you can use core-vsdoc.js to get Intellisense support in any of your code that is using core.js.
In addition to namespace support, you will also find a lightweight StringBuilder object in core.js which is useful if you are assembling HTML with your code so you can avoid the overhead that comes with string concatenation.
There is a lot more that I will be covering going forward, such as common jQuery techniques, currying and callbacks. Please check back for that content.
Find me on Twitter: @smallsharptools.
April 29th, 2009 at 9:07 am
[...] bookmarks tagged javascript Brennan's Blog » Blog Archive » Modern JavaS... saved by 3 others ifon1stdate bookmarked on 04/29/09 | [...]