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

7 篇文章 0 订阅
本文探讨了在JavaScript中如何使用setTimeout替换setInterval时的常见错误,包括回调函数引用问题和清除定时器时机的混淆。通过实例解析和错误分析,揭示了全局作用域下函数引用的重要性,并提供了正确操作代码示例。
摘要由CSDN通过智能技术生成

使用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>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值