为什么这个限制函数中的事件侦听器表现得像那样? [英] why does the event listener in this throttling function behave like that?

查看:23
本文介绍了为什么这个限制函数中的事件侦听器表现得像那样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我学习 javascript 中的节流时,我遇到了一个事件监听器我无法解释的行为.这是一个简单的节流功能.

While I was learning about throttling in javascript, I came upon an event-listener behavior that I can't explain. Here is a simple throttling function.

const btn=document.querySelector("#throttle"); 
      
    // Throttling Function 
    const throttleFunction=(func, delay)=>{ 
      
      // Previously called time of the function 
      let prev = 0;  
      console.log(prev); //This gets called only once and it is even before the button is clicked
      return (...args) => { 
        // Current called time of the function 
        let now = new Date().getTime();  
  
        // Logging the difference between previously  
        // called and current called timings 
        console.log(now-prev, delay);  //This however doesn't get called before the button is clicked
          
        // If difference is greater than delay call 
        // the function again. 
        if(now - prev> delay){  
          prev = now; 
  
          // "..." is the spread operator here  
          // returning the function with the  
          // array of arguments 
          return func(...args);   
        } 
      } 
    } 
    btn.addEventListener("click", throttleFunction(()=>{ 
      console.log("button is clicked") 
    }, 1500)); 

<button id="throttle">Click Me</button> 

我有两个问题.

  1. 为什么 let prev = 0; 只被调用一次?即为什么不prev 每次调用该函数时都会重置为 0?
  2. 我还注意到 let prev = 0; 在按钮被点击之前被调用,为什么会发生这种情况?为什么在点击按钮之前没有调用其余的函数?
  1. Why does let prev = 0; only get called once? i.e why doesn't prev get reset to 0 every time the function is called?
  2. I have also noticed that let prev = 0; gets called before the button is even clicked, Why does this happen? and why doesn't the rest of the function get called before the button is clicked as well?

这是我找到上面代码的地方.我在 MDN 上查看了 addEventListener 但无济于事.任何帮助将不胜感激.

This is where I found the code above. I have looked into addEventListener on MDN but to no avail. Any help would be appreciated.

推荐答案

.addEventListener() 方法将一个函数的引用作为它的第二个参数,它可以在你的按钮被点击时调用.所以这样的事情将无法将函数添加为点击事件处理程序:

The .addEventListener() method takes a reference to a function as its second argument, which it can invoke when your button is clicked. So something like this will fail to add the function as a click event handler:

const sayHello = () => console.log("hello");
btn.addEventListener("click", sayHello());

在上面的 JavaScript 示例中:

In the above example JavaScript:

  1. 看到对addEventListener()

评估它的参数,这意味着调用 sayHello() 函数.

Evaluates its arguments, which means calling the sayHello() function.

2.1.sayHello() 运行并返回 undefined

2.1. sayHello() runs and returns undefined

使用 "click"undefined(评估参数)调用 addEventListener() 方法

Calls the addEventListener() method with "click" and undefined (the evaluated arguments)

sayHello() 上面是一个函数调用,所以它会在你的事件监听器被添加和任何点击发生之前执行,导致 sayHello 的返回值被用作 addEventListener() 的第二个参数,所以上面的代码将评估为:

Above the sayHello() is a function call, so it will execute as your event listener is added and before any clicks occur, resulting in the return value of sayHello being used as the second argument to addEventListener(), so the above code will evaluate to something like:

const sayHello = () => console.log("hello");
btn.addEventListener("click", undefined);

要正确地将引用传递给事件侦听器,您需要传递一个函数,该函数随后可以在发生单击时由 JS 调用:

To correctly pass a reference to the event listener, you would need to pass a function that can then later be invoked by JS when a click occurs:

btn.addEventListener("click", sayHello);

考虑到这一点,当您添加事件侦听器时,您的 throttleFunction() 参数会被调用,这意味着 throttleFunction 本身不是传递的内容作为 addEventListener() 的第二个参数,而是返回值.如果您将回调提取到 throttleFunction,这可能会更清楚一些:

With that in mind, your throttleFunction() argument is being called when you add your event listener, which means that the throttleFunction itself isn't what is being passed as the second argument to addEventListener(), but rather the return value. This may be a little clearer if you extract the callback to throttleFunction:

const fn = () => {console.log("button is clicked")};
// invoking the `throttleFunction` function with `()`
const clickHandler = throttleFunction(fn, 1500);
btn.addEventListener("click", clickHandler); // clickHandler is a reference to a function (a non-invoked/called function)

由于您的 throttleFunction() 函数被调用,从 throttleFunction 返回的函数被用作 addEventListener() 的参数,不是throttleFunction 本身.返回的函数只有在发生点击时才会执行.结果,let prev = 0; 在第一次调用throttleFunction 时执行一次,也就是添加click 事件监听器时,但是返回的函数执行了多次,因为JS 只会在你点击你的按钮.

Since your throttleFunction() function is being invoked, the returned function from throttleFunction is being used as the argument for addEventListener(), not the throttleFunction itself. The returned function is only then executed when a click occurs. As a result, let prev = 0; is executed once when the throttleFunction is first called which is when click event listener is added, but the returned function is executed multiple times, as JS will call it only when you click on your button.

这篇关于为什么这个限制函数中的事件侦听器表现得像那样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆