(For background, please check out parts 1, 2, and 3 before reading this post.)
One of the problems about private local variables inside closures is that you can’t see them. Well, duh, you might say, that’s what private means after all. Point taken, but there’s one scenario where it would be really nice to be able to check those enclosed (enclosured?) variables: debugging.
Now, I’m not going to get into the whole argument here about debugging versus testing. I’m of the firm belief that you should be writing unit tests as you go along (and I’m only not doing it here because the code I write for these posts is mainly pedagogical in nature). Once you have properly built a supporting unit test structure around your code, it shouldn’t matter what your local variables contain: the unit tests will test your external interfaces and if they work as expected then you’re gold as far as the behavior of your code is concerned. Anyway…
Back to our stopwatch example – the initial simple version. Now, I will admit that, as written, it’s ruddy hard to unit test this little object. That’s because I’m embedding, essentially, a random process in the middle: the current time. To properly test this I should extract out the code snippet that gets the current time (the weird-looking +new Date()
statement) and build it in as an external interface that I can then mock. But let’s say I want to debug this code after I’ve called start()
and before I call stop()
. As written, there’s no way I can inspect the local variable startTime
if I’m in a debugger. The stopwatch
object is opaque.
Enter the debugger
keyword. This is a reserved word in JavaScript and is designed to trigger a program breakpoint when executed. If there is no JavaScript debugger present, it’s just ignored, but if you are running under Firebug or whatever developer tools your browser provides (I use Firefox myself) the debugger will gain control and hand control over to you.
So what, you may say. Whether you have a manual breakpoint or use this fancy debugger
statement, you still have the same problem: you can’t see inside the opaque stopwatch
object. True. . . unless you execute the debugger
statement inside the context of the closure itself.
Let’s add an inspect()
method to the stopwatch object:
var stopwatch = (function () { var startTime = -1, now = function () { return +new Date(); }, start = function () { startTime = now(); }, stop = function () { if (startTime === -1) { return 0; } var elapsedTime = now() - startTime; startTime = -1; return elapsedTime; }, inspect = function () { debugger; }; return { start: start, stop: stop, inspect: inspect }; }());
Notice that this new function is inside the closure. If we call stopwatch.inspect()
from the Firebug console, for example, the breakpoint will be triggered, and will be triggered inside the context of the closure. We will be able to see the value of startTime
(and modify it if required).
In Firebug, you get something that looks like this:
Now the program execution has stopped inside the closure, you can inspect the value of startTime
to your heart’s content.
Now, I’ll be the first to recognize that this technique is a little invasive – after all, you have to write this special function and expose it publicly – but it does nicely solve the “I can’t inspect the values of the locals inside my closure/module” problem.
Now playing:
Stewart, Rod - These Foolish Things
(from It Had to Be You... The Great American Songbook)
No Responses
Feel free to add a comment...
Leave a response
Note: some MarkDown is allowed, but HTML is not. Expand to show what's available.
_emphasis_
**strong**
[text](url)
`IEnumerable`
* an item
1. an item
> Now is the time...
Preview of response