CosmoCode is a Berlin based IT service provider focusing on CMS, Wikis and Web2.0
Great software. Bright people. Happy customers!
Mail info@cosmocode.deTel +49 (30) 814504070
Closures is a concept of programming languages, which is easy to use (and often used), but it (and its consequences) is rarely understood.
Closures simply means:
If you can see a variable declared outside, you can use it.
That sounds trivial for global variables:
var name = 'enzo';
function myName () { alert( name + ' erhardo'); }
myName(); // will alert 'enzo erhardo';
The power of closures is unleashed when declaring the function inside of another function. With closures you can use the local variables of the outer function.
There is a common problem when using eventhandler or timer functions in javascript: you often have to pass object pointer to eventhandler. Especially when coding OO-style, you want to invoke instance methods instead of globals functions - precise: you want to pass the “this” pointer.
The following example binds an onclick handler to a html element which starts a interval timer:
function StopWatch ( node ) {
this.node = node;
}
StopWatch.prototype.start = function () {
this.started = new Date();
this.itvid = setInterval( **timer**, 500 ) ;
this.node.style.backgroundColor = 'lightgreen';
}
StopWatch.prototype.stop = function () {
if ( this.itvid ) clearInterval( this.itvid ) ;
}
StopWatch.prototype.update = function () {
this.node.innerHTML = new Date() - this.started;
}
var stopwatch = new StopWatch ( document.getElementById('test') );
stopwatch.update() ;
}**
The problem is the timer function. You want to pass the “this” pointer to it. With closures, the solution is simple. The trick is to define a local function inside of the function start. The local function can use all local variables. Unfortunalety this wont work for the this pointer, but you can copy it to a local variable self:
function StopWatch ( node ) {
this.node = node;
}
StopWatch.prototype.start = function () {
**var self = this;**
this.started = new Date();
**var timer = function () { self.update(); };**
this.itvid = setInterval( **timer**, 500 ) ;
}
StopWatch.prototype.stop = function () {
if ( this.itvid ) clearInterval( this.itvid ) ;
}
StopWatch.prototype.update = function () {
this.node.innerHTML = new Date() - this.started;
}
var stopwatch = new StopWatch ( document.getElementById('test') );
The function start can be abbreviated to
function start () {
** var self = this;
this.itvid = setInterval( function () { self.update(); }, 500 ) ;**
}
This is a common used idiom when using eventhandler and timer: creating inner functions and using outer variables with closures.
If you want to see the script in action, click here. This example creates two stopwatches which can be started and stopped independently.
About CosmoCode
Subscribe
Benedetto Cattarinich
2007/02/07 10:03
Great! I was looking for this explaination and code from a long time. I'd be glad to read other articles from the same author. Benedetto (Benny)Cattarinich Web Developer