前端进阶 | 面试必考—— JavaScript手写定时器

在前端面试中,JavaScript 定时器相关的知识是一个常考的重点,它涉及到 JavaScript 的单线程特性、异步执行机制等重要概念。下面我们就来详细梳理一下关于 JavaScript 定时器的相关知识。

一、JavaScript 单线程特性

JavaScript 是单线程的,这意味着它只有一个主线程来执行代码。这就导致如果在主线程上有一个耗时的操作,后续的代码都需要等待这个操作完成才能执行。例如,如果有一个无限循环:

arduino 复制代码
while(true){

}

在这个循环执行期间,其他的代码都无法执行,包括定时器。

二、 setTimeout 函数

基本概念

setTimeout 是一个异步执行的计时器,它接收两个参数:一个回调函数和一个时间(以毫秒为单位)。回调函数会被放入事件循环(event loop)中,但不会立即执行,而是会在主线程执行完后,等待指定的时间后再执行。

示例代码

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>手写定时器</title>
</head>
<body>
    <button id="btn2">提前关闭setTimeout定时器</button>
    <button id="btn">关闭定时器</button>
    <script>
        const timeout = setTimeout(function(){
            console.log('---')
        }, 1000);

        // 同步代码
        console.log(123);

        const btn = document.getElementById('btn');
        const btn2 = document.getElementById('btn2');
        btn.addEventListener('click', function(){
            clearTimeout(interval);
        });
        btn2.addEventListener('click', function(){
            clearInterval(timeout);
        });

        const interval = setInterval(function(){
            console.log('哈....')
        }, 1000);
    </script>
</body>
</html>

注意事项

  • 即使 setTimeout 的时间设置为 0 秒,它也不会立即执行,而是会在主线程执行完后再执行。
  • setTimeout 并不一定会在指定的时间后立即执行,因为它需要等待主线程上的代码执行完毕。

定时器 ID

setTimeout 函数会返回一个定时器 ID,这个 ID 可以用于后续关闭定时器,使用 clearTimeout 函数,传入定时器 ID 即可关闭定时器。

三、 setInterval 函数

setInterval 函数用于每隔指定的时间重复执行一个回调函数。它的使用方式和 setTimeout 类似,同样接收一个回调函数和一个时间间隔(毫秒)作为参数。

示例代码

javascript 复制代码
const interval = setInterval(function(){
    console.log('哈....')
}, 1000);

关闭定时器

可以使用 clearInterval 函数来关闭 setInterval 创建的定时器,需要传入定时器 ID。

四、 高频面试题------使用 setTimeout 实现 setInterval

实现思路

可以使用递归调用 setTimeout 来模拟 setInterval 的功能。

示例代码

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>定时器</title>
</head>
<body>
    <script>
        function customSetInterval(fn, time) {
            let intervalId = null;

            function loop() {
                intervalId = setTimeout(() => {
                    fn();
                    loop();
                }, time);
            }
            loop();
            return () => clearTimeout(intervalId);
        }
        const interval = customSetInterval(function() {
            console.log('定时器ing...');
        }, 1000);
        setTimeout(() => {
            interval();
        }, 5000);
    </script>
</body>
</html>

代码解释

  • 函数定义与参数customSetInterval 函数接收两个参数,fn 是要定期执行的回调函数,time 是执行回调函数的时间间隔(单位为毫秒)。

  • 变量声明let intervalId = null; 声明了一个变量 intervalId,用于存储 setTimeout 返回的定时器 ID,初始值为 null

  • 内部递归函数 loop

    • intervalId = setTimeout(() => { fn(); loop(); }, time);:在 time 毫秒后执行箭头函数,箭头函数内部先调用 fn() 执行回调函数,然后递归调用 loop() 函数,以实现定时重复执行的效果。
    • 每次调用 setTimeout 都会返回一个新的定时器 ID,并将其赋值给 intervalId
  • 启动循环loop(); 调用 loop 函数,启动定时器的循环执行。

  • 返回清除定时器的函数return () => clearTimeout(intervalId); 返回一个箭头函数,该函数用于清除定时器。调用这个返回的函数时,会传入 intervalIdclearTimeout 函数,从而停止定时器的执行。

  • 使用自定义定时器

    • const interval = customSetInterval(function() { console.log('定时器ing...'); }, 1000); 调用 customSetInterval 函数,传入一个匿名函数作为回调函数,以及时间间隔 1000 毫秒(即 1 秒),并将返回的清除定时器的函数赋值给 interval

    • setTimeout(() => { interval(); }, 5000); 使用 setTimeout 函数,在 5000 毫秒(即 5 秒)后调用 interval() 函数,从而停止定时器的执行。

五、结语

通过以上内容的学习,我们对 JavaScript 定时器的相关知识有了更深入的理解,这些知识在前端面试中是非常重要的,希望大家能够掌握。

相关推荐
天若有情6732 分钟前
【C++原创开源】formort.h:一行头文件,实现比JS模板字符串更爽的链式拼接+响应式变量
开发语言·javascript·c++·git·github·开源项目·模版字符串
天***88526 分钟前
Edge 浏览器离线绿色增强版+官方安装包,支持win7等系统
前端·edge
漫游的渔夫14 分钟前
别再直接 `json.loads` 了!AI 返回的 JSON 坑位指南
前端·人工智能
软件工程师文艺26 分钟前
从0到1:Claude Code如何用React构建CLI应用
前端·react.js·前端框架
Yuk丶28 分钟前
UE4客户端开发技术问题汇总
面试·ue4·图形学·ue4客户端开发
M ? A36 分钟前
Vue 迁移 React 实战:VuReact 一键自动化转换方案
前端·vue.js·经验分享·react.js·开源·自动化·vureact
yuki_uix37 分钟前
重排、重绘与合成——浏览器渲染性能的底层逻辑
前端·javascript·面试
何陋轩1 小时前
OpenAI Codex深度解析:终端里的AI代码特工,一个指令重构整个项目
人工智能·面试
止观止1 小时前
拥抱 ESNext:从 TC39 提案到生产环境中的现代 JS
开发语言·javascript·ecmascript·esnext
沃尔威武1 小时前
调试黑科技:Chrome DevTools时间旅行调试实战
前端·科技·chrome devtools