views:

106

answers:

1

Hey there,

I've got a prototype having a method I can add callbacks with:

/*
 * Add a callback function that is invoked on every element submitted and must return a data object.
 * May be used as well for transmitting static data.
 * 
 * The callback function is supposed to expect a jQuery element as single parameter 
 * and must return a data object (for additional data to be sent along with the one already given upon initialization).
 * Adding multiple callback functions results in those functions being invoked in the same order as they were added.
 * 
 * 1) Therefore subsequent assignments to the same key in the data array override those that were performed by a previous callback function.
 * 2) If data_arg = true is given, the data returned by the callback function that was previously called is given to the new_callback as 2nd argument, so it can be manipulated.
 *    However, even if it isn't, the unchanged data must be returned anyway to have any effect.
 */

this.add_data_callback = function(new_callback, data_arg) {

    if(this.data_callback) {
        old_callback = this.data_callback;

        if(!data_arg) {
            //alert('add it');
            //alert(old_callback);
            //alert(new_callback);

            this.data_callback = function(element) {
                //alert('do it');
                //alert(old_callback);
                //alert(new_callback);
                return jQuery.extend(old_callback(element), new_callback(element));
            };
        }
        else {
            this.data_callback = function(element, data) {
                return new_callback(element, old_callback(element));
            };
        }
    }
    else {
        //alert('add the first');
        //alert(new_callback);
        this.data_callback = new_callback;
    }
};

(Please ignore the else part for data_arg = true as it's not relevant.)

In my concrete case I'm adding three callback functions. If this.data_callback() is finally invoked for an element, however, it results in the whole thing looping infinitely. In my attempt to track the bug down, the alerts above (yeah, I know that there're debugging tools for that but it was way more comfortable like that) delivered the following insight into the issue:

  1. The anonymous function / closure (the one that contains jQuery.extend()) is called. new_callback contains the 3rd callback function. old_callback contains another...
  2. anonymous function which is called. new_callback contains the 2nd callback function. old_callback should contain the 1st callback function, but actually it's yet another...
  3. anonymous callback which is called. new_callback contains the 2nd callback function again. old_callback contains the anonymous function
  4. ...

Now, what do I miss? Is it some strange closure magic or just some obvious bug I'm apparently unable to see?

Thanks in advance!

+2  A: 

Why isn't old_callback defined with var?

var old_callback = this.data_callback;

As it is, it's a global variable. Maybe it's declared elsewhere but it still looks suspicious to me.

Pointy
judging by the use of the `this` keyword, the code posted looks like part of a class, and old_callback could be a private property of that class.
Andy E
Awwwww.@Andy: It isn't.
codethief
@codethief: carry on then ;-) @Pointy: +1.
Andy E
Ha! Well missing `var` is a daemon that haunts everybody!
Pointy