• Private JavaScript Variables
Aug 26 2007
I find myself needing to generate unique IDs in JavaScript a lot lately. Mostly this happens when I'm creating a lot of elements dynamically and I need to assign some unique ID to them so that I can find them later. And I need to do this because I've realised that storing pointers to elements in JavaScript uses a LOT more memory than just storing the ID of an element and finding it later with getElementById().
So anyway, what's a good way of generating unique IDs?
A simple way is to just keep a counter going and increment it every time you access it, like this:
var guid_counter = 0; for (var i=0;i < 100;i++) {
// create a new <div> element
var div = document.createElement('div');
// assign a unique ID and increment counter
div.id = 'div_' + (guid_counter++);
// append to the page
document.body.appendChild(div);
}
With this you'll end up with 100 <div>s with IDs from "div_0" to "div_99". But our guid_counter is just sitting out there in the open! Someone could come along (like us making a typo) and write guid_counter = 0 or guid_counter-- and mess everything up! We could end up with 2 elements with the same ID!
We can improve on this by using a private variable. Private variables give us more control over global variables like our guid_counter, because we can choose when and how they are accessed and updated. Let's create a function which contains our guid counter as a private variable:
// 'guid' is assigned to the return value of this outer function
var guid = (function() {
// same guid counter, but we keep it hidden inside here
var guid_counter = 0;
// return a function that has access to guid_counter
return function() {
// whenever guid() is called, return and increment the counter
return guid_counter++;
};
})(); // note the () - this executes the outer function right now!
If this is the first time you're seeing this syntax (or the hundredth) it can be a bit confusing. Really, we're doing the same thing as this:
function generate_guid_function() {
// nothing outside of generate_guid_function() can access this
var guid_counter = 0;
// return a function that has access to guid_counter
return function() {
// return and increment the counter
return guid_counter++;
};
}
// 'guid' is assigned to return value of generate_guid_function()
var guid = generate_guid_function();
The magic of all this is in JavaScript Closures. The inner function has access to guid_counter because of where it's defined, but our code outside has no way to change or access guid_counter. This is exactly like private instance variables in Java and other languages.
Now, we can safely rely on our guid() function to generate unique IDs without worrying about our guid_counter being touched:
for (var i=0;i < 100;i++) {
// create a new <div> element
var div = document.createElement('div');
// assign a unique ID from our new guid() function
div.id = 'div_' + guid();
// append to the page
document.body.appendChild(div);
}
Tags: javascript private variables