irpas技术客

js 使用setTimeout()代替setInerval()易错点_JonyXin27

未知 4159

使用setTimeout()代替setInerval()易错点

跟着b站尚硅谷的JS基础视频自己在做 定时器案例 时出现了一些小错误。

案例描述 正确

错误

实现过程

不想看的可跳过此部分

//Code01 //一些获取元素对象初始化 let box1 = document.getElementById("box1"); //粉色盒子 let box1Width = parseInt(getStyle(box1, "width")); //获取粉色盒子的width,这么写是为了提高浏览器的兼容性 let btn = document.getElementById("btn"); //键盘按钮 let line = document.getElementById("line"); //黑线 let id, flag = false; //id为定时器的唯一标识符 flag用来在定时函数中判断按钮是否按下 //btn按钮的响应事件 btn.onclick = function () { flag = true; }; /* * 定义一个函数,用来获取指定元素的当前的样式 * 参数: * obj 要获取样式的元素 * name 要获取的样式名 */ //正常浏览器的方式,具有getComputedStyle()方法 //IE8及其以下,使用 对象.currentStyle.样式名 的方法 function getStyle(obj, name) { return window.getComputedStyle ? getComputedStyle(obj, null)[name] : obj.currentStyle[name]; } setInterval()实现 Code02 //使用setInterval()实现 id = setInterval(function () { if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } //box1碰到line就停止 if ((box1.offsetLeft + box1Width) == line.offsetLeft) { clearTimeout(id); } }, 50); setTimeout()实现 //使用setTimeout()来实现 function moveRight() { //box1碰到line就停止 if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } id= setTimeout(moveRight, 50); // console.log(id); // id = setTimeout("moveRight()", 50); //报错:VM42:1 Uncaught ReferenceError: moveRight is not defined 看网上说是要在全局作用域下才能这么写 if ((box1.offsetLeft + box1Width) == line.offsetLeft) { // console.log("id " + id); clearTimeout(id); } }; moveRight(); 遇到的错误 setTimeout()中回调函数中应引用问题 //Code03 //使用setTimeout()来实现 function moveRight() { if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } //box1碰到line就停止 // // 判断box1右边是否碰到了线 if ((box1.offsetLeft + box1Width) == line.offsetLeft) { clearTimeout(id); } id = setTimeout("moveRight()", 50); //【报错1】:VM42:1 Uncaught ReferenceError: moveRight is not defined }; moveRight(); 报错:VM42:1 Uncaught ReferenceError: moveRight is not defined 解决方法 //Code04 id = setTimeout(moveRight, 50); 原因

因为我是在window.onload属性下实现的该功能,我看一个博主说得要在该函数得要在全局作用域下才能写成"moveRight()"。

原因感觉不是特别清除,但是能够解决【求解答】

回调函数内id = setTimeout()和clearTimeout(id)使用顺序问题

哈哈哈哈,其实我Code03代码中存在错误,不知道有没有人发现,那就是我标题中所说的问题

正确操作 //Code05 //使用setTimeout()来实现 function moveRight() { if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } //setTimeout()在前面 id = setTimeout(moveRight(), 50); //clearTimeout()在后面 if ((box1.offsetLeft + box1Width) == line.offsetLeft) { clearTimeout(id); } }; moveRight(); 原因:

如果将clearTimeout(id)写在前面

如果将clearTimeout(id)写在后面

进一步解释 错误顺序 //使用setTimeout()来实现 function moveRight() { //box1碰到line就停止 if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } if ((box1.offsetLeft + box1Width) == line.offsetLeft) { //在控制台中输出 console.log("id " + id); clearTimeout(id); } id = setTimeout(moveRight, 50); //在控制台中输出 console.log(id); }; moveRight();

我们可以看到clearTimeout()清除的是上一个延时定时器id = 14,而没有把新生成的演示定时器id = 15清除。

正确顺序 //使用setTimeout()来实现 function moveRight() { //box1碰到line就停止 if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } id = setTimeout(moveRight, 50); //在控制台中输出 console.log(id); if ((box1.offsetLeft + box1Width) == line.offsetLeft) { //在控制台中输出 console.log("id " + id); clearTimeout(id); } }; moveRight();

我们可以看到clearTimeout()清除的是新添加的定时构造函数。

完整代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>定时器01</title> <style> #box1 { position: absolute; top: 100px; left: 50px; width: 100px; height: 100px; background-color: pink; } #line { position: absolute; top: 0; left: 300px; width: 0; height: 1000px; border-left: 1px solid #000; } </style> <script> window.onload = function () { //一些获取元素对象初始化 let box1 = document.getElementById("box1"); //粉色盒子 let box1Width = parseInt(getStyle(box1, "width")); //获取粉色盒子的width,这么写是为了提高浏览器的兼容性 let btn = document.getElementById("btn"); //键盘按钮 let line = document.getElementById("line"); //黑线 let id, flag = false; //id为定时器的唯一标识符 flag用来在定时函数中判断按钮是否按下 btn.onclick = function () { flag = true; }; // //使用setInterval()实现 // id = setInterval(function () { // if (flag) { // box1.style.left = box1.offsetLeft + 5 + "px"; // } // //box1碰到line就停止 // if ((box1.offsetLeft + box1Width) == line.offsetLeft) { // clearTimeout(id); // } // }, 50); //使用setTimeout()来实现 function moveRight() { //box1碰到line就停止 if (flag) { box1.style.left = box1.offsetLeft + 5 + "px"; } id = setTimeout(moveRight, 50); // console.log(id); // id = setTimeout("moveRight()", 50); //报错:VM42:1 Uncaught ReferenceError: moveRight is not defined 看网上说是要在全局作用域下才能这么写 if ((box1.offsetLeft + box1Width) == line.offsetLeft) { // console.log("id " + id); clearTimeout(id); } }; moveRight(); }; /* * 定义一个函数,用来获取指定元素的当前的样式 * 参数: * obj 要获取样式的元素 * name 要获取的样式名 */ //正常浏览器的方式,具有getComputedStyle()方法 //IE8及其以下,使用 对象.currentStyle.样式名 的方法 function getStyle(obj, name) { return window.getComputedStyle ? getComputedStyle(obj, null)[name] : obj.currentStyle[name]; } </script> </head> <body> <button id="btn">点击按钮以后box1向右移动</button> <div id="box1"></div> <div id="line"></div> </body> </html>


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #js #定时器案例 #时出现了一些小错误 #box1