问题描述
在我学习 throttling in javascript 时,我发现了一种我无法解释的事件侦听器行为。这是一个简单的节流功能。
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>
我有两个问题。
- 为什么
let prev = 0;
只被调用一次?即为什么不prev
每次调用该函数时都会重置为 0? - 我还注意到
let prev = 0;
在按钮被点击之前就被调用了,为什么会发生这种情况?为什么在点击按钮之前没有调用其余的函数?
This 是我找到上面代码的地方。我在 MDN 上查看过 addEventListener
但无济于事。任何帮助将不胜感激。
解决方法
.addEventListener()
方法将一个函数的引用作为它的第二个参数,它可以在您的按钮被点击时调用。所以这样的事情将无法将函数添加为点击事件处理程序:
const sayHello = () => console.log("hello");
btn.addEventListener("click",sayHello());
在上面的 JavaScript 示例中:
-
看到对
的调用addEventListener()
-
评估它的参数,这意味着调用
sayHello()
函数。2.1.
sayHello()
运行并返回undefined
-
使用
addEventListener()
和"click"
(评估参数)调用undefined
方法
sayHello()
上方是一个函数调用,因此它会在添加事件侦听器时以及在发生任何点击之前执行,从而导致 sayHello
的返回值被用作 { 的第二个参数{1}},因此上面的代码将评估为:
addEventListener()
要正确地将引用传递给事件侦听器,您需要传递一个函数,该函数随后可以在发生单击时由 JS 调用:
const sayHello = () => console.log("hello");
btn.addEventListener("click",undefined);
考虑到这一点,当您添加事件侦听器时会调用您的 btn.addEventListener("click",sayHello);
参数,这意味着 throttleFunction()
本身并不是作为第二个参数传递给 {{1 }},而是返回值。如果您将回调提取到 throttleFunction
,这可能会更清楚一些:
addEventListener()
由于您的函数正在被调用,因此 throttleFunction
返回的函数被用作 const fn = () => {console.log("button is clicked")};
// invoking the function ------------\/
const clickHandler = throttleFunction(fn,1500);
btn.addEventListener("click",clickHandler); // clickHandler is a reference to a function (a non-invoked/called function)
的参数,而不是 ThrottleFunction 本身。返回的函数只有在发生点击时才会执行。因此,throttleFunction
在第一次调用 ThrottleFunction 时执行一次,也就是添加点击事件监听器时,但返回的函数会执行多次,因为 JS 只会在您点击按钮时调用它。