1 两种定时器
1.1 延迟定时器
setTimeout(code, time, par…)
- code: 延迟一段时间之后,做需要做的事,
可以是个function(时间到了自动调用),string(不推荐) - time:延迟的事件
- parma1…parmaN:定时器完成需要执行code时,作为参数传入code中
IE9及其以下存在兼容问题
document.onclick = function () {
setTimeout(
function (a, b, c) {
console.log(a + b + c);
}, 1000, 1, 2, 3
);
}
1.2 间隔定时器
setInterval(code, time, par…) 结束之前反复执行
2 清除定时器
2.1 清除延时定时器
每个定时器都会有一个返回值,这个返回值就是定时器的id
- 这个id是唯一数字
- 是一个正整数
clearTimeout(id) :id是要清除的定时器编号
2.2 定时器的问题
频繁去开启一个定时器的话,定时器会启动多个,然后如果去记录一个定时器返回的id 的话就会造成后面的定时器覆盖前面的定时器id的情况
清除间隔定时器的方法:管理定时器
-
每次开启定时器的时候先清除上一次的定时器
var t1; var t2; var t3; var btns = document.querySelectorAll('button'); btns[0].onclick = function () { clearTimeout(t1); clearTimeout(t2); clearTimeout(t3); t1 = setTimeout( function (a, b, c) { console.log('定时器1'); }, 1000 ); t2 = setTimeout( function (a, b, c) { console.log('定时器2'); }, 2000 ); t3 = setTimeout( function (a, b, c) { console.log('定时器3'); }, 3000 ); console.log(t1, t2, t3); } btns[1].onclick = function () { clearTimeout(t3); }
这样虽然定时器返回的id会改变,但是因为已经清了上次的定时器,所以事件只会执行一次
-
开关,在上一次的定时器未关闭的情况下不允许开启下一次定时器
btns[0].onclick = function () { if (onOff) { t1 = setTimeout( function (a, b, c) { console.log('定时器1'); }, 1000 ); } onOff = false; } btns[1].onclick = function () { clearTimeout(t1); onOff = true; }
3定时器注意事项
3.1 定时器里的this指向
this是谁调用,就指向谁
但是定时器是js本身就定义好的函数,被定义在window
下面
所以是通过window进行调用的
所以定时器里的this就指向window
定时器this指向的解决方法
定义一个_this
变量存储事件函数中的this指向
3.2 不推荐第一个参数(code)使用字符串
- 影响性能
- 首先解析字符串
- 解析函数然后执行
有两次解析的过程
- web安全 xss注入
可以通过输入字符串的方式调用函数
但是如果输入一个无限循环的函数,就会进入死循环,这就是xss注入
解决方法
后端和前端共同解决
3.3 第二个参数time最小执行时间
-
默认为0,但是执行代码任有延迟(>= 4ms)
-
经典面试题
for (var i = 0; i < 5; i++) { setTimeout(function () { console.log(i); }); }
for循环执行非常快,导致setTimeout获取的i是for循环结束之后的i
3.4 传参问题
- IE9以下不支持定时器传参
- 给定时器内的有名函数传参会使函数立即执行(因为加了括号)
解决方法
-
字符串,但是会被解析两次并且有xss注入的安全问题(不推荐)
setTimeout('fn(参数)', 1000);
-
用匿名函数包一下
setTimeout(function() { fn(par); }, 1000);
-
bind
先复习一下传值传址的问题
getNewAge === window.getNewAge,指向的是window
解决方法就是使用bind()
改变了this的指向变为obj
同理bind就可以进行参数传递var obj = { age: 18, getAge: function(a, b, c) { console.log(a, b, c); } } var getNewAge = obj.getAge.bind(obj, 1, 2, 3); getNewAge();
用于定时器
setTimeout(fn.bind(null, 2), 1000); // 改变this指向window可以写成null function fn(n) { console.log(n); }