Monday, November 28, 2011

A Delve into Some Details

My last programming post was a bit of an upbeat ramble in response to a question about the previous post which was a bit of a grumpy gripe. I would like to revisit that gripe one last time. Javascript DOM event handling started me down the road to Crankyville, so allow me to reflect on some of the minute straws my camel was carrying that day.

When learning languages and programming interfaces, I naturally tend to use Google as my easiest reference when poking around with new things. Unfortunately Google is like high school: it confuses popularity with authoritativeness. The number one link when searching on the topic of JavaScript event handlers shows an example that looks essentially like this:
thing.eventHandler = function (eventData) {
  var local1, local2;
  if (!eventData){
    var eventData = window.event;
  }
  //The magic happens.
}
I want to be clear up front, this works and turns out to be perfectly correct, but it still bothered me. Being a professional programmer cultivates a certain amount of anal retentiveness in you. Computer code does exactly what you tell it to, not what you meant it to. Plus, not all languages are strict about checking whether you are making sense or telling it gibberish before going off and potentially wrecking things. In this case, a couple things set my programmer sense off, and they are both related to that if statement above.

First, the reason you have to have the if statement in the first place: WebKit browsers pass event data as a parameter to the event handler function, but Gecko browsers store event data in the window object's event property. The if statement checks to see if there is data in the parameter, and if not attempts to retrieve it from the window property. I have not bothered to look up whether this comes about because of competing standards or too-permissive specifications, but either way the situation has to be handled. And it has to be handled every single time. Compatibility issues of this sort are certainly nothing new, but they do nothing but add code. Picking one style over the other does not break the old code because both cases are covered, so why not declare one the winner and move forward without needing the additional testing. (Note to browser vendors: pick the parameter form. I suspect using the global window.event will interfere with any potential attempts at parallel processing events. Not to mention using globals is just bad form.)

The second issue is much more subtle, and much more just me being a jerk about these sorts of things. The function has a formal parameter called eventData. The function declares a variable eventData. Thus eventData appears to have two different definitions in the same place. Programmers refer to visibility of things as the "scope" of those things. JavaScript has two types of scopes, visible to everything everywhere (global scope) and visible only within the function where it is declared (function scope). When I see two different definitions of something in the same scope it get an ache behind the eyes. Thankfully, it turned out I was not alone in that assessment. I mentioned Douglas Crockford's JSLint tool previously in passing, and indeed it flags eventData in the code above as being re-declared. The question then became: why this is flagged as bad style but not actually an error. JavaScript, I learned, allows the redefinition of things within the same scope; the second definition is essentially ignored and the system uses the thing already given that name. In this code, it is not a problem. In long, complicated functions written by people used to different rules from different languages, I can see this causing subtle defects. And so could Mr. Crockford. Having someone backup your gut feelings is always nice.
thing.eventHandler = function (eventData) {
  var local1, local2;
  if (!eventData){
    eventData = window.event;
  }
  //The magic happens.
}
In the end we get the above code, with one problem solved, and one problem not. The change is quite subtle, but it makes those aches in my head go away. As for the piece not solved, well, what can I say? Learning to cope with things you can't change is just as much a part of being a programmer as in any other aspect of life.

No comments: