setTimeout的第三个参数作用

本文探讨了JavaScript中setTimeout函数的第三个参数及其应用。通过实例展示了如何使用闭包和函数参数解决循环中setTimeout的问题,并介绍了该参数的多种用途。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

说起来你可能不相信,setTimeout居然有第三个参数,我以前也没用过这个,但最近看到一个代码解决了for循环里面加入了setTimeout的例子,下面一起看看这个setTimeout第三个参数。

for(var i = 0; i<6; i++){
    setTimeout(function(){
        console.log(i);
    },1000);
}

看到上面的这个for例子,相信很多人都能脱口而出,它会连续输出6次6,因为setTimeout是一个异步操作,而等到执行setTimeout时,for循环已经执行完毕,这时的i已经等于6,所以输出6次的6。

闭包
那么怎么改呢?说说最常见的改法就是使用闭包。

for(var i=0; i<6; i++){
    (function(j){
        setTimeout(function(){
            console.log(j);
        },j*1000);
    })(i);
}

通过闭包,将i的变量驻留在内存中,当输出j时,引用的是外部函数A的变量值i,i的值是根据循环来的,执行setTimeout时已经确定了里面的的输出了。

函数传参
还有一种就是给setTimeout添加第三个参数。

for(var i=0;i<6;i++){
    setTimeout(function(j){
        console.log(j);
    },i*1000,i);
}

由于每次传入的参数是从for循环里面取到的值,所以会依次输出0~5。 看了上面的代码,相信你对这个setTimeout的第三个参数作用大概了解了,是的,它就是给setTimeout第一个函数的参数。 翻一下MSDN文档,里面确实有记录setTimeout第三个及后面的参数的。下面我们来看看这个代码

function sum(x,y,z){
    console.log(x+y+z);
}
setTimeout(sum,1000,1,2,3);

上面第二行打印出了6,1+2+3=6(11是setTimeout timeId)。 可以看出,第三个及以后的参数都可以作为sum函数的参数。

第三个参数作为函数

var i=0;
setTimeout(function(){
    console.log('第二次'+i)
},3000,setTimeout(function(){
    console.log('第一次'+i);
    i++;
},1000));

最后依次输出为 第一次0 第二次1 可以看到第三个参数还可以是先执行,然后再执行函数。 今天就到这里了,有没有get到这个点,我翻了之前自己写过的关于setTimeout和setInterval的相关文章,都没有谈到第三个参数的,中文的w3c教程也没看到。 利用好setTimeout的第三个参数,有时候会有意向不到的收获。希望这篇文章对你有所帮助。

### 解决鼠标快速离开时未触发 `mouseleave` 事件的问题以及 `addEventListener` 第三个参数的含义 #### `addEventListener` 第三个参数的含义 在 JavaScript 中,`addEventListener` 的第三个参数用于指定事件监听器的行为。这个参数可以是一个布尔值或一个对象。如果是一个布尔值,它决定了事件是否以捕获阶段执行。 - 当该参数为 `true` 时,表示事件监听器会在捕获阶段被调用。 - 当该参数为 `false`(默认值)时,表示事件监听器会在冒泡阶段被调用[^1]。 此外,从现代浏览器开始支持,这个参数也可以是一个对象,包含以下属性: - `capture`:布尔值,等同于之前的布尔值参数,决定事件是在捕获阶段还是冒泡阶段被处理。 - `once`:布尔值,表示事件监听器是否只调用一次,之后自动移除。 - `passive`:布尔值,表示事件监听器是否会调用 `preventDefault()`。如果设置为 `true`,则浏览器假定 `event.preventDefault()` 永远不会被调用[^2]。 ```javascript element.addEventListener('click', function(event) { console.log('Event triggered'); }, { capture: true, once: true, passive: true }); ``` #### 解决鼠标快速离开时未触发 `mouseleave` 事件的问题 当鼠标快速移动时,可能会出现 `mouseleave` 事件未被触发的情况。这通常是因为鼠标的移动速度超过了事件监听器的响应速度。以下是几种解决方法: ##### 方法一:使用定时器延迟隐藏 通过引入定时器来延迟隐藏 `tooltip`,可以避免因鼠标快速移动而导致的未触发问题。这种方法确保即使鼠标快速移出,也会在一定时间后隐藏 `tooltip`。 ```javascript let hideTimeout; function handleMouseEnter() { clearTimeout(hideTimeout); showTooltip(); } function handleMouseLeave() { hideTimeout = setTimeout(() => { hideTooltip(); }, 300); // 延迟300毫秒隐藏 } ``` ##### 方法二:检查 `relatedTarget` 利用 `mouseleave` 事件中的 `relatedTarget` 属性,可以判断鼠标是否进入了同一父级下的其他子元素。如果 `relatedTarget` 不属于当前元素的子节点,则认为鼠标真正离开了整个区域,并执行隐藏逻辑。 ```javascript function handleMouseLeave(event) { const parentElement = event.currentTarget; if (!parentElement.contains(event.relatedTarget)) { hideTooltip(); } } ``` ##### 方法三:手动控制 `tooltip` 的显示与隐藏 通过绑定 `visible` 属性到父组件的状态中,可以手动控制 `tooltip` 的显现和隐藏。这种方法适用于 Vue 或 React 等框架中的场景。 ```vue <template> <div @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave"> Hover me <span v-if="isTooltipVisible">Tooltip Content</span> </div> </template> <script> export default { data() { return { isTooltipVisible: false, }; }, methods: { handleMouseEnter() { this.isTooltipVisible = true; }, handleMouseLeave() { this.isTooltipVisible = false; }, }, }; </script> ``` ##### 方法四:结合防抖技术 使用防抖(debounce)技术可以减少因频繁触发事件而导致的问题。通过限制事件的触发频率,确保 `mouseenter` 和 `mouseleave` 的处理更加稳定。 ```javascript function debounce(func, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); }; } const debouncedMouseEnter = debounce(handleMouseEnter, 200); const debouncedMouseLeave = debounce(handleMouseLeave, 200); ``` ### 注意事项 - 在复杂布局下,可能需要调整 `tooltip` 的位置以确保其始终可见。 - 如果 `delay` 被设置为非零值,需注意延迟时间内用户可能已移出目标区域,因此应合理设置延迟时间。 - 使用 `relatedTarget` 属性时,需确保浏览器兼容性,部分老旧浏览器可能不支持该属性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值