在写网页交互效果时,经常需要延迟执行一段代码。比如点击按钮后过两秒再弹出提示,这时候就会用到 setTimeout。但很多时候,不只是简单地延迟执行,还需要把一些数据传进去,这就涉及到了 setTimeout 传参的问题。
直接传函数名加参数?别被坑了
新手常会这么写:
setTimeout(myFunction(arg), 1000);
这样其实不对。因为带括号就等于立刻执行函数,setTimeout 拿到的是执行后的返回值,而不是函数本身。结果就是函数没等就跑了,延迟失效。
正确方式一:利用闭包
可以包一层匿名函数,让它延迟执行:
setTimeout(function() {
myFunction(arg);
}, 1000);
或者用箭头函数更简洁:
setTimeout(() => myFunction(arg), 1000);
这种方式最常见,也最容易理解,适合大多数场景。
正确方式二:使用 setTimeout 的额外参数
其实 setTimeout 支持传多个参数,第三个以后都会原封不动地传给回调函数:
function greet(name, age) {
console.log(`你好,${name},你${age}岁了`);
}
setTimeout(greet, 1000, '小明', 25);
这段代码会在一秒后输出“你好,小明,你25岁了”。这个特性很多人不知道,但其实兼容性也不错,现代浏览器都支持。
实际场景:防抖提示框
比如做一个搜索建议功能,用户每输入一次就发请求太浪费。可以加个延时,等他停顿一下再查:
let timer;
inputElement.addEventListener('input', function(e) {
const query = e.target.value;
clearTimeout(timer);
timer = setTimeout((q) => {
fetchSuggestions(q);
}, 300, query);
});
这里用到了传参的方式,把当前输入内容传进延迟函数里。同时用 clearTimeout 防止频繁触发。
注意 this 指向问题
如果在对象方法里用 setTimeout,要注意 this 可能会丢失:
const user = {
name: '张三',
sayHi() {
setTimeout(function() {
console.log(this.name); // undefined
}, 100);
}
};
解决办法是用箭头函数,或者提前保存 this:
sayHi() {
setTimeout(() => {
console.log(this.name); // 张三
}, 100);
}
setTimeout 虽然小,但用好它能让页面更流畅。传参这一步看似简单,写错却容易让人抓耳挠腮。掌握这几种方式,下次写延时逻辑时就能稳稳拿捏了。