javascript - 了解 geeksforgeeks 的去抖代码
问题描述
有人可以帮我理解这段代码片段是如何工作的吗?
在来自希腊的极客中,他们有以下代码片段
<html>
<body>
<button id="debounce">
Debounce
</button>
<script>
var button = document.getElementById("debounce");
const debounce = (func, delay) => {
let debounceTimer
return function() {
const context = this
const args = arguments
clearTimeout(debounceTimer)
debounceTimer
= setTimeout(() => func.apply(context, args), delay)
}
}
button.addEventListener('click', debounce(function() {
alert("Hello\nNo matter how many times you" +
"click the debounce button, I get " +
"executed once every 3 seconds!!")
}, 3000));
</script>
</body>
</html>
从以下节流和去抖动函数之间的区别中,它说,仅在没有待处理的操作(并且在特定秒之后)时才发出
在这里,我看不到任何 if 条件来检查是否有待处理的操作。
从他们说的文章中
> If the debounce button is clicked only once, the debounce function
> gets called after the delay. However, if the debounce button is
> clicked once, and again clicked prior to the end of the delay, the
> initial delay is cleared and a fresh delay timer is started. The
> clearTimeout function is being used to achieve it.
因此,每次单击按钮时,都会清除计时器并启动新计时器(并且可能还会触发新操作),这听起来可能不像我从 SFO 答案中读到的那样
另外,有人可以func.apply(context, args), delay)
逐行解释如何使用或代码吗?
解决方案
在这里,我看不到任何 if 条件来检查是否有待处理的操作。
没有进行明确的检查,而是 3 秒是用于决定任何事情的最大窗口。
从引用的答案https://stackoverflow.com/a/57524083
Debounce(1 秒):嗨,我是那个 ^^ 机器人的表弟。只要你一直 ping 我,我就会保持沉默,因为我喜欢在你上次 ping 我之后的 1 秒后才回复。我不知道,是因为我的态度有问题,还是因为我只是不喜欢打扰别人。换句话说,如果您在上次调用后 1 秒内一直要求我回复,您将永远不会得到回复。是啊是啊……去吧!骂我粗鲁。
因此,如果有一个点击动作并且 3s 已经过去,你运行事件处理函数,简而言之,它是一种“捎带”。汇集您的所有需求,然后在确定您不再要求时立即尝试
关于第二部分func.apply(context, args), delay)
- 这是因为 javascript 中作用域的性质而使用的。在您的示例中,他们没有使用与this
关键字概念相关的任何内容,只是this.innerText = 'hello'
在警报后添加了这一行,您会希望按钮的文本更改为“hello”,并且确实会起作用。但现在替换func.apply(context, args)
为func(args)
,它不会工作......
为什么?由于this
关键字的性质,它是根据调用函数的位置而不是从源代码内部的位置推断出来的
因此,当 3ssetTimeout
调用此函数后() => func( args)
,this
指向setinterval
并且您知道this.innerText = 'hello'
setInterval 对象没有任何意义(是的,一切都是 javascript 中的对象,甚至函数!)
apply的作用是它允许您操纵将在调用时在给定函数内“解析”的上下文this
;无论您想要的函数位于类、对象还是仅在全局范围内,只要它是可访问的,您都可以将您的参数和一个对象传递给它,它将假定为它的this
function fullName(greeting) {
alert(greeting + ', ' + this.firstName + " " + this.lastName);
}
var person1 = {
firstName: "John",
lastName: "Doe"
}
var person2 = {
firstName: "Santiago",
lastName: "Adan"
}
fullName.call(person1, "hello");
fullName.call(person2, "hola");
推荐阅读
- c# - 更新不同类型但具有相同基类的记录
- r - Flip Dataframe in R based on Dates?
- r - 使用两个数据框但一个数据表
- ibm-cloud - 当问题 ID 名称中有正斜杠时,如何创建容器注册表配置问题豁免?
- sql - 选择中的划分和子查询
- javascript - 使用 lodash 按子值对对象进行排序
- python - 如何从字符串中删除 WindowsPath 和括号
- testing - 除了需要将“test”和“fixture”作为全局变量注入之外,TestCafe 真的需要自己编译测试代码吗?
- javascript - 在 JavaScript 中的元素之前插入节点
- java - Hibernate 不能映射到表?