计时器
- setTimeout():一次性计时器;
- setInterval():连续计时器;
用法:
两者除了一次性和连续,其他基本完全一样。
1.两个参数
一般情况下计时器都是两个参数
格式:setTimeout(f,time)=>f为计时到达后需要执行的函数,time为计时器的时间。
举例:setTimeout(function(){console.log(1)},1000)//=>一秒后输出1
同时:setTimeout(f)// 等同于setTimeout(f, 0)
但是有时也会有多个参数:
setTimeout(function(a,b){console.log(a+b)},1000,1,2)//=>1,2分别为a,b的实参
** 需要注意的是:如果回掉函数是对象的时候,其中的this会指向全局对象
var a="3"
var obj={
a:1,
b:function(){console.log(this.a)}
}
setTimeout(obj.b,1000) //=>输出“3” this指向window对象
var str="全局";
var obj={
str:"对象",
func:function(){
//var done=this.test setTimeout(done,1000);
setTimeout(this.test,1000);
},
test:function(){
console.log(this.str);//=>"全局"
}
}
obj.func()
解决作用域的办法:
1.使用bind、call、apply来绑定thissetTimeout(obj.b.bind/call/apply(obj),1000)
2.将obj.b放在函数中执行setTimeout(function(){obj.b()},1000)
使用计时器可以有效防止抖动事件,扯到防抖动,势必会扯出节流,接下来就谈谈这两个默认的小妖精。
使用setTimeout实现一个setInteval
function timer(){
var time=setTimeout(function(){
document.write(2)
timer();
clearTimeout(time)
},1000)
}
timer()
防止抖动:
- 函数防抖是指对于在事件被触发n秒后再执行的回调,如果在这n秒内又重新被触发,则重新开始计时。
- 思路:利用计时器setTimeout和clearTimeout,只要触发事件,就会销毁上一次的计时器,重新计时,计时结束后才会触发回掉函数的事件。
- 适用于:
表单组件输入内容验证;
防止多次点击导致表单多次提交等情况;
防止函数过于频繁的不必要的调用。
比如一个提交按钮,用户多次点击,然后计时器就会不断被销毁又重新创建,直到用户停止点击并且时长达到计时器时间,然后再执行提交事件。
html:
<button id="btn">提交</button>
js:
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 3000);
};
}
function sayHi() {
console.log('防抖成功');
}
var btn = document.getElementById('btn');
btn.addEventListener('click', debounce(sayHi));
节流:
- 节流的核心思想:不然该触发事件执行的太过频繁,通过定时器保证一段时间内只能执行一次。
- 适用于:
搜索框智能提示(每打一个字都有相应的智能检索,但是只在这个字打完为止才有效);
检测鼠标的坐标(mousemove);
function scrollFn(){
console.log(1)
}
function throttle(method,delay,duration){
var timer=null;
var begin=new Date();
return function(){
var context=this, args=arguments;
var current=new Date();
clearTimeout(timer);
if(current-begin>=duration){
method.apply(context,args);
begin=current;
}else{
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
}
window.onmousemove=throttle(scrollFn,100,500);