Blog


The Seedy Underbelly of JavaScript

I was watching my del.icio.us/popular links today and saw "JavaScript.com" scroll by. Amused, I decided to take a look. I remember looking at sites like this back in '98-'99 when I wanted to do "cool" effects, just copy-and-pasting snippets into a page and hoping that it would work.

So I started to look through the snippets on their web site. I knew that some bad JavaScript code was still written - but dear god - there's some awful code on their site. I can't even dignify it with a link, for fear that some PageRank may bleed their way.

I then stumbled across a so-called "Add/Remove an Event" snippet. Intrigued, I decided to take a look. You may remember that I won the Quirksmode addEvent contest last year with this entry. Honestly, it's pretty rough - I've moved on and use other techniques these days.

Now, I'd like you to take a look at my code and compare it to the code that was presented on JavaScript.com:

My Original addEvent/removeEvent Code

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}
function removeEvent( obj, type, fn ) {
  if ( obj.detachEvent ) {
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
  } else
    obj.removeEventListener( type, fn, false );
}

The "New" addEvent/removeEvent snippet from JavaScript.com

//------------------------------------
// addEvent
function addEvent(obj,type,fn){
    try{
        if(obj.addEventListener) obj.addEventListener(type,fn,false);
        else if(obj.attachEvent){
            obj["e"+type+fn]=fn
            obj[type+fn]=function(){ obj["e"+type+fn](window.event)}
            obj.attachEvent("on"+type,obj[type+fn]);
        }
    } catch(e){/*alert(e)*/}
}

//------------------------------------
// removeEvent
function removeEvent(obj,type,fn){
    if(obj.removeEventListener) obj.removeEventListener(type,fn,false);
    else if(obj.detachEvent){
        obj.detachEvent("on"+type,obj[type+fn])
        obj[type+fn]=null
        obj["e"+type+fn]=null;
    }
}

There's a couple points about this snippet that I find particularly amusing:

  1. It's presented under the copyright of some other blogger: askApache.com (although, this seems to be more of a case of mistaken identity than anything else).
  2. There's an extra try/catch block that silently garbles up any errors. What errors? You're binding an event!
  3. There's an extra check for IE (obj.detachEvent) but doesn't throw any error when the event isn't able to be bound.

In all, I'd hate to be the pour soul trying to debug my first JavaScript programming and not knowing why I wasn't getting any relevant errors. We should get Sun to start flexing their JavaScript trademark muscle and take down sketchy sites like this, passing them over to non-profit organizations who could actually move JavaScript out of the dark ages.

Update: The askApache webmaster has replied in the comments - it was a misunderstanding and the relevant copyright info is being put in place. Yay! That being said, JavaScript.com still has really poor-quality code. It's like we need a reset switch for the world of JavaScript knowledge - delete all the old, bad, code and stick with the current, high quality, code and libraries.

Tags: snippets, code, programming, javascript, tips, piracy

Fast JavaScript Max/Min

I've been saving this technique for a while now - it's simple, but it's good. What's the fastest way to find the largest, or smallest, number in an array?

There's a bunch of implementations floating around - including some nicely object-oriented approaches in Prototype. However, none of them can compare to the raw simplicity of this:

Array.max = function( array ){
    return Math.max.apply( Math, array );
};

Array.min = function( array ){
    return Math.min.apply( Math, array );
};

The premise behind this technique is simple (and obvious once you see it): Just find any built-in JavaScript function that takes unlimited arguments - it'll now be just as easy to adapt it for Array-wide use. By using JavaScript's .apply() method on a built-in function you can pass in an array of unlimited arguments.

After "discovering" this for myself I found out that it's mentioned in the "Rhino" book, which made me feel stupid. Oh well, it's a great trick and its one that more people should know.

Tags: tips, javascript, programming

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.


Hosting provided by the cool dudes at Engine Yard.