views:

58

answers:

3

I generally write code that looks like this (but with many more handlers).

$(document).ready(function() {

    $("#next").click(function() {
        doStuff();
    });

    $("#prev").click(function() {
        doSomeOtherStuff();
    });

    $("#link").hover(function() {
        doSomeTotallyOtherStuff();
    });
});

Is this the best way of doing this? Should I do it differently? Paul Irish's presentation suggests it's a bad idea. Is that true?

+1  A: 

This should be fine as long you don't do it in a loop or some other code that runs more than once (i.e. a recurring function call). Otherwise there's not much difference between one anon function and one named function. it's when you have 100 identical anonymous functions that's a problem.

ex:

$("#someID").click(function(){})

is okay,

for (var i in somelistofIDs) {
    $(i).click(function(){})
}

is not, because you've created 100 anonymous functions instead of one named function.

EDIT

of course, if you're wrapping a single function call in a closure, you're doing it wrong, you can just pass the function itself.

cthom06
Yeah, the closure has lots of lines, not just one.
Rich Bradshaw
Your `for` example is a little risky b/c of how closures bind external variables, but as long as you are careful and know what you are doing I don't see the problem.
Gabe Moothart
@Gabe the problem is that you create 100 instances of the function, rather than just 1.
cthom06
A: 

One reason that it's useful to define your functions the old boring way is that you get names to look at in stack traces.

$(function() {
  function nextClickHandler() { ... };

  $('#next-button').click(nextClickHandler);
});

It's not safe to use a function name in a function expression:

  $('#next-button').click(function nextClickHandler() { // DO NOT DO THIS
  });

which is sort-of unfortunate but there you go.

Pointy
+1  A: 

We like to use the object literal pattern and named functions. I'd rewrite your example like this:

$(function() {
  Example.somegrouping.init();
});

var Example.somegrouping = {
  init: function() {
    // set up listeners
    $("#next").click(this.onNextClick);
    $("#prev").click(this.onPrevClick);
    $("#link").hover(this.onLinkHover);
  },
  onNextClick: function() {
    // do some stuff
  },
  onPrevClick: function() {
    // do some stuff
  },
  onLinkHover: function() {
    // do some stuff
  }    
};

Why? Well, it makes it easier to reuse event handlers in other places without resorting to triggers. The naming of the fuction can help self-document your code. Testing/debugging is easier. The object literal only adds one entry to the global namespace, so there is little chance for collisions with other scripts your page might be using.

ScottE
This is exactly how I've ended up writing stuff, would be interested to hear if there are any botches with it.
Rich Bradshaw
@Rich - works great for us. Code reusability is higher as well. It encourages more modular programming.
ScottE