JS 定时器 setInterval() 和 setTimeout() 面试题:定时器传参和返回值,异步任务

题目如下, fn1() 和 fn2() 结果?

   function fn1() {
        for (var i = 0; i < 4; i++) {
            var tc = setTimeout(function (i) {   
                console.log(i);  
                clearTimeout(tc);    
                },10, i) 
        }
    }

    function fn2() {
        for (var i = 0; i < 4; i++) {
            var tc = setInterval(function (i, tc) {
                console.log(i);
                clearInterval(tc);   
            }, 10, i, tc)
        }
    }

    fn1();  
    fn2();  

答案:

    fn1();  // 0,1,2
    fn2();  // 0,1,2,3,3,3,3,3.....

解析:

function fn1() {
        for (var i = 0; i < 4; i++) {
            var tc = setTimeout(function (i) {    // var 变量回被提升,变量值会被后面覆盖
                console.log(i);  // 打印定时器被传进来的参数i
                clearTimeout(tc);    // tc变量最后的值是最后一个定时器的ID: 4
                },10, i)   // i 的传参会一直被保留,知道定时器启动时被调用
        }
    }

    function fn2() {
        for (var i = 0; i < 4; i++) {
            var tc = setInterval(function (i, tc) {
                console.log(i);    // 打印定时器被传进来的参数i
                clearInterval(tc);   // 这里的 tc 是每次被传进来的定时器的ID
            }, 10, i, tc)  // 传参的 i, 和定时器ID值 tc 会被保留
        }
    }

这道题涉及定时器的传参和返回值,以及JS执行顺序异步问题。

定时器语法:
var intervalID = scope.setInterval(func, delay, [arg1, arg2, ...])
var timeoutID = scope.setTimeout(function[, delay, arg1, arg2, ...])

第一个参数func是执行函数,第二个参数 dalay 是延迟时间, 后面的参数都是传给执行函数的参数。

定时器的返回值是定时器的计数器,从1开始计数,表示定时器的ID, 这个ID 传递给 clearInterval() 和 clearTimeout() 来清除定时器。注意,intervalID 和 timeoutID 会公用一个编号池。

异步任务:

定时器在JS中被作为异步任务,放到任务队列中,当主线程任务执行完之后,会来执行异步任务。

两个函数的执行过程:

fn1函数:

setTimeout 和 setInterval 面试题 fn1函数执行过程.png

fn2函数:

setTimeout 和 setInterval 面试题 fn2 函数执行过程.png

你可能感兴趣的:(JS 定时器 setInterval() 和 setTimeout() 面试题:定时器传参和返回值,异步任务)