函数指针与setInterval定时器混合使用时的相爱相杀

284 阅读3分钟

什么是函数指针

const fn=()=>{  //fn:函数的内容, fn():函数执行后的结果
        console.log("w");
        return fn  
    }

在上面的函数中,fn就是代码块中箭头函数的函数指针,fn指代的就是函数体本身。
这里要区分 fn, fn() 的区别:fn——指函数体本身,fn()——函数执行结束后的结果。
毕竟fn(),加了括号就表示立即执行。

什么是定时器setInterval

具体内容可参见 setInterval MDN,这里只考虑第一、二个参数(函数和延迟时间),暂不考虑第三个参数。

let intervalID = setInterval(func, delay, [arg1, arg2, ...]);

上述代码的意思就是每经过delay毫秒,执行一次func。

两者混合使用时会怎么样

  1. fn中return,setInterval传入参数fn()
    console.log("q");
    const fn=()=>{  
        console.log("w");
        return fn  
    }
    setInterval(fn(),2000) 
    console.log("e");

上述代码的输出是:q, w, e, w, w, w, w...

2. fn中return,setInterval传入参数为一个函数,该函数函数体中调用fn

    console.log("q");
    const fn=()=>{  
        console.log("w");
        return fn  
    }
    setInterval(()=>{fn()},2000) 
    console.log("e");

上述代码的输出是:q, e, w, w, w, w, w...

3. fn中不return,setInterval传入参数fn()

    console.log("q");
    const fn=()=>{  
        console.log("w");
    }
    setInterval(fn(),2000) 
    console.log("e");

上述代码的输出是:q, w, e

4. fn中不return,setInterval传入参数fn

    console.log("q");
    const fn=()=>{  
        console.log("w");
    }
    setInterval(fn,2000) 
    console.log("e");

上述代码的输出是:q, e, w, w, w, w, w...

5. fn中return,setInterval传入参数fn

    console.log("q");
    const fn=()=>{  
        console.log("w");
        return fn 
    }
    setInterval(fn,2000) 
    console.log("e");

上述代码的输出是:q, e, w, w, w, w, w...

总结规律,得出结论

上述5个示例中:

  1. 1和3的输出结果中w在e前面,即只有setInterval中传入的第一个参数是fn()时,fn函数才会立即执行;
  2. 2、4、5的输出结果是一样的,这说明只有setInterval传入的第一个参数是函数体本身,定时器就会重复执行传入的函数,但又因为传入的是函数指针(即函数体)而非带括号的立即执行语句fn(),所以fn不会在console.log("e")之前立即执行;
  3. 3中没有重复输出,因为这个例子中传入的参数是fn()且fn函数没有return任何东西,对于fn()而言,它的本质只是把fn执行一遍,但它什么都不是(fn的函数类型是void,什么都没返回,相当于啥也不是),所以setInterval接收到第一个参数时感受应该就和下面的猫猫表情包一样,就很迷惑,这是个啥???我明明是要接收函数来着,这给我传了个啥???所以它不会去重复执行fn,因为我们也没把fn传给setInterval;
4. 4、5中输出结果是一样的,这说明只要传入的参数是函数体本体,那么函数最后是否return并不影响定时器的执行。

后面的console.log语句为什么会先于前面的setInterval执行

因为直接输出语句console.log属于微任务,而定时器setInterval属于宏任务,在js执行机制中,微任务总是先于宏任务执行。
关于微/宏任务的知识点,这个b站上的小视频->js宏任务与微任务<-讲的蛮生动的,有兴趣的小伙伴可以去瞅瞅~