【问题标题】:addEventListener calls the function without me even asking it toaddEventListener 在我什至没有要求的情况下调用了该函数
【发布时间】:2023-02-05 10:41:37
【问题描述】:

所以我们有一个页面:

<span id='container'>
    <a href='#' id='first'>First Link</a>
    <a href='#' id='second'>Second Link</a>
</span>

并想添加一些点击事件:

first.addEventListener('click', function(){alert('sup!');})

奇迹般有效!但是,当您将第二个参数设为外部函数时:

function message_me(m_text){
    alert(m_text)
}

second.addEventListener('click', message_me('shazam'))

它立即调用函数。我怎样才能阻止这个?很烦人!

这是一个现场演示:http://jsfiddle.net/ey7pB/1/

【问题讨论】:

  • 由于第二个参数需要一个函数参考,你需要提供一个。对于有问题的代码,您将立即调用该函数并传递其结果(即不明确的).在匿名函数中调用该函数(如您的第一个示例)或将函数更改为返回一个功能(可能不理想)。
  • 为什么这不理想?这似乎反对 D.R.Y.在我设置的 4 个左右的 addEventListeners 中复制我的函数,不是吗?
  • 另一种选择是将所需消息存储为元素的属性,然后将函数绑定为 second.addEventListener('click', message_me) 并让它从属性而不是参数中检索消息。

标签: javascript addeventlistener


【解决方案1】:

引用伊恩的answer

由于第二个参数需要一个函数参考,你需要提供一个。使用有问题的代码,您将立即调用该函数并将其传递给结果(这是undefined...因为所有函数所做的都是alert并且不返回任何东西)。在匿名函数中调用函数(如您的第一个示例)或更改函数以返回函数。

function message_me(m_text){
    alert(m_text)
} 

second.addEventListener('click', 
    function() {
        message_me('shazam');
    }
);

这是更新的fiddle

【讨论】:

  • 我认为你应该更新你接受的答案,因为传递函数而不调用它,并且绑定 - 在这里可能是更好的选择。
  • 您能解释一下为什么您认为 bind 是更好的选择吗?
  • @clav 谢谢我从 2-3 小时开始就一直在寻找这个
【解决方案2】:

由于第二个参数需要一个函数参考,你需要提供一个。使用有问题的代码,您将立即调用该函数并将其传递给结果(这是undefined...因为所有函数所做的都是alert并且不返回任何东西)。在匿名函数中调用函数(如您的第一个示例)或更改函数以返回函数。

你可以这样做:

function message_me(m_text){
    alert(m_text);
}

second.addEventListener('click', function () {
    message_me('shazam')
});

或这个:

function message_me(m_text){
    return function () {
        alert(m_text);
    };
}

second.addEventListener('click', message_me('shazam'));

演示:http://jsfiddle.net/tcCvw/

【讨论】:

    【解决方案3】:

    或者你可以使用 .bind

    function message_me(m_text){
        alert(m_text);
    }
    
    second.addEventListener('click', message_me.bind(this, 'shazam'));
    

    检查MDN Documentation 关于“关闭”

    【讨论】:

    • +1 绑定应该是可行的方法——不确定 4 年前是否可用,但绝对是今天的首选方法,而不是创建匿名函数
    • 绑定的好建议,绝对应该是公认的答案。 OP可以改吗?
    • @vol7ron“而不是创建匿名函数.bind() 仍然创建了一个新功能。我不明白为什么它会更可取。此外,它会总是设置 this 值,这意味着如果处理程序期望它是元素,那么 .bind() 将打破它。这绝对不是灵丹妙药。
    • @VLAZ 你让我退休了 ;) 这里有几件事。 (1) 在这篇评论中,箭头函数()=&gt;{...} 和 ES6 还是比较新的,也因为 IE 不支持它而被劝阻。 (2) 匿名函数实际上是更长的 function(){...} 语法,可读性较差。 (3) 虽然构建底层函数可能会更慢,但调用 bind() 函数要快得多 (1.5-2X),这在循环中可能很重要。我承认你关于 this 被强行设置的观点 :) JS 的美妙之处在于选项。
    【解决方案4】:

    使用箭头函数的现代 ES6 解决方案

    second.addEventListener('click', () => message_me('shazam'))
    

    【讨论】:

      【解决方案5】:

      2022年

      我知道以下可能性:

      选项 1(匿名函数)

      function message_me(m_text){
          alert(m_text);
      }
      
      second.addEventListener('click', function () {
          message_me('shazam')
      });
      

      选项 2(回调 fn 调用匿名 fn)

      function message_me(m_text){
          return function () {
              alert(m_text);
          };
      }
      
      second.addEventListener('click', message_me('shazam'));
      

      选项 3(绑定())

      function message_me(m_text){
          alert(m_text);
      }
      
      second.addEventListener('click', message_me.bind(this,'shazam'));
      

      选项 4(箭头 fn)

      function message_me(m_text){
          alert(m_text);
      }
      
      second.addEventListener('click', () => {
          message_me('shazam')
      });
      

      我个人喜欢使用 (选项 4) 箭头函数,因为你得到 包括上下文。另一个不错的解决方案是绑定 (选项 3).这个变体让我有点困扰的是你必须明确地包括上下文。这很容易被遗忘。选项1很好,这可能是过去的标准方式。到选项 2我只能说:它有效,但就我的口味而言,它看起来很尴尬。

      但基本上,您必须从语法中获取您认为最容易理解的内容。因为最后你要记住这么多,然后让你的生活更轻松,把你最能记住的东西拿走。在我的情况下,选项 4 和选项 3 那么选项 1 和选项 2 对我来说不是替代方案。

      【讨论】:

        猜你喜欢
        • 2021-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-23
        • 1970-01-01
        相关资源
        最近更新 更多