简体   繁体   中英

Is it ok to execute undefined callback in event listeners?

I am writing a code that performs a function on click on a set of elements. It has a revalidate function. This revalidate function is fired on window resize. It checks if certain conditions are not fulfilled after resize then nothing should be done on click on body. This is an oversimplified version. Code:

var myFunction = function() {
    // do something
}

var myCallback = myFunction;

$(".myClass").on("click", myCallback);

$(window).resize(function(){
    if(//certain conditions are met) {
        myCallback = undefined;
    }
    else {
        myCallback = myFunction
    }
});

I know I can use jquery off to detach the handler. But the actual code is more complex. It is a plugin like code where if I click event is bound in certain conditions inside the plugin definition. If I use off then to use On again appropriately I might have to run the whole plugin code once again; that beats the purpose of revalidate function. So,

Is it ok to execute undefined callback in event listeners?

PS: I have been also reading about jQuery.noop . Seems like it's the exact situation to use that.

Your code doesn't call an undefined function, because the variable myCallback is only evaluated when you bind the event handler, not every time the event occurs. To have the question you ask, it would have to be the following code:

$(".myClass").on("click", function(e) {
    myCallback.call(this, e);
});

When myCallback is set to undefined this will get an error, complaining that undefined is has no property call . What you should write is:

$(".myClass").on("click", function(e) {
    if (myCallback) {
        myCallback.call(this, e);
    }
});

When you do this,

$(".myClass").on("click", myCallback);

A reference to myCallback function is sent. When reassigning it, the callback (reference) sent to the on function will not be changed.

What you probably wanted to do is something like this

$(".myClass").on("click", function(){ myCallback(); });

Now when myCallback is undefined , you'll get an error saying it's not a function. You could assign it an empty function instead of undefined :

myCallback = function(){};

Alternately, you could check for the condition within the click handler:

var condition = true;
var myFunction = function() {
  if( !condition )
    return;
  // do something
}

$(".myClass").on("click", myFunction);

$(window).resize(function(){
  if(//certain conditions are met) {
    condition = false;
  }
  else {
    condition = true;
  }
});

The way which you tried didn't work as you didn't pass your callback physically, just a pointer to it. So doing

myCallback = undefined;

Doesn't clear your callback, it just changes pointer to undefined variable. jQuery saves information about your callback before you change the pointer. That's why it didn't work.

Consider refactoring to:

  let guardian = true;
  let clickHandler = function () {
    if (guardian) {
      /* your code */
    }
  };

  $(".class").on("click", clickHandler);

  $(window).resize( function () {
    if (/* certain conditions are met */) {
      guardian = false;
    } else {
      guardian = true;
    }
  });

In that case, we change guardian variable during resizing and check against it in our click handler. You don't have to on/off your callback handlers in such a case.

It's certainly not pretty code, and steps should be taken to make it obvious to other developers (or future-you) that this callback may not be a callback later on, but jQuery's .on method will not try and run anything that equates (think == ) to false.

Therefore, setting your callback to undefined will not error.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM