【问题标题】:Is it ok to execute undefined callback in event listeners?可以在事件监听器中执行未定义的回调吗?
【发布时间】:2017-03-24 15:26:02
【问题描述】:

我正在编写一个代码,该代码在单击一组元素时执行一项功能。它具有重新验证功能。此 revalidate 函数在窗口调整大小时触发。它检查调整大小后是否不满足某些条件,然后单击正文时不应执行任何操作。这是一个过于简化的版本。代码:

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
    }
});

我知道我可以使用 jquery off 来分离处理程序。但实际代码更复杂。它是一个类似于代码的插件,如果我单击事件在插件定义内的某些条件下绑定。如果我使用off,然后适当地再次使用On,我可能不得不再次运行整个插件代码;这超出了revalidate 函数的目的。所以,

在事件监听器中执行未定义的回调可以吗?

P.S:我也一直在阅读有关 jQuery.noop 的信息。似乎是使用它的确切情况。

【问题讨论】:

  • undefined 是不可执行的,所以我不推荐它。您始终可以将其设置为空函数:myCallback = function () {};
  • 我的意思是...你试过吗?如果可以的话,那会很快告诉你。不过,更好的选择是在 myFunction 中简单地有一个条件。
  • @KevinB 是的,我试过了,效果很好。
  • 变量myCallback 不会在每次事件发生时进行评估,而是在您分配事件处理程序时进行评估。重新分配 myCallback 不会使处理程序未定义。
  • @KevinB 获得第二意见可能不是一个坏主意。浏览器行为可能有很大不同,测试所有可能的选项可能不可靠或不可行。这里的某个人可能能够引用一个可以更明确地回答或提出一些可能的陷阱的规范。

标签: javascript jquery html dom-events


【解决方案1】:

您的代码不会调用未定义的函数,因为变量myCallback 仅在您绑定事件处理程序时进行评估,而不是每次事件发生时。要问你的问题,它必须是以下代码:

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

myCallback 设置为未定义时,会出现错误,抱怨undefined 没有属性call。你应该写的是:

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

【讨论】:

  • 也可以执行以下操作:$("body").on("click", undefined); 虽然我实际上并不需要它。我只是出于好奇而问。
  • 我怀疑 jQuery 会简单地忽略它,因为它会检查其参数的类型以确定您正在调用的函数的形式,而这与任何签名都不匹配。
【解决方案2】:

当你这样做时,

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

发送了对myCallback 函数的引用。重新赋值时,发送给on函数的回调(引用)不会改变。

你可能想做的是这样的

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

现在当myCallbackundefined 时,您会收到一条错误消息,指出它不是函数。你可以给它分配一个空函数而不是undefined

myCallback = function(){};

或者,您可以检查 click 处理程序中的条件:

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;
  }
});

【讨论】:

    【解决方案3】:

    您尝试的方式不起作用,因为您没有物理传递回调,只是一个指向它的指针。就这样吧

    myCallback = undefined;
    

    不清除你的回调,它只是改变指向未定义变量的指针。 jQuery 在您更改指针之前保存有关您的回调的信息。这就是它不起作用的原因。

    考虑重构为:

      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;
        }
      });
    

    在这种情况下,我们会在调整大小的过程中更改 Guardian 变量,并在我们的点击处理程序中对其进行检查。在这种情况下,您不必打开/关闭回调处理程序。

    【讨论】:

      【解决方案4】:

      这当然不是漂亮的代码,应该采取措施让其他开发人员(或未来的你)明白这个回调可能不是以后的回调,但是 jQuery 的 .on 方法不会尝试运行任何等同于(认为==)为假。

      因此,将回调设置为 undefined 不会出错。

      【讨论】:

        猜你喜欢
        • 2011-03-08
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 1970-01-01
        • 2015-06-30
        • 1970-01-01
        • 2021-09-13
        • 1970-01-01
        相关资源
        最近更新 更多