setTimeout运行原理与常见用法
2017-01-18 23:38

这是我的网站建好后写的第一遍文章,就先拿setTimeout来写写吧。

    大家都知道setTimeout是js中的定时器,也就是在代码将在给定的时间后进行执行。

<script>
    function calltest(){
        console.log("mm");
        setTimeout(function(){
            console.log("oo");
        },0);
        console.log("nn");
    }
    calltest();
</script>


上面这段代码中使用了setTimeout定时器代码,代码中“oo”是在0毫秒后执行打印输出的,对于不理解setTimeout的小伙伴们来说,可能就会认为calltest方法执行的结果是mm----oo---nn。确实如果从感性上认识的话,oo代码是在0毫秒后执行的,这个也就是说是立即执行的啦,应该是先打印oo再打印nn啊。要理解这个就要理解一下js的执行机制。

    我们都知道js是单线程的,既然是单线程的又怎么会有定时执行的功能呢?对于熟悉诸如java等的多线程语言的人来说,他们可以另外启动一个线程,在这个线程中wait或者sleep相应的时间后再执行一段代码,犹如定时的功能般。而这类多线程的语言中会存在多个线程同时调用一个方法,在某些情况下会由于变量资源等的相互持有等待而造成死锁的现象。相对他们来说,js只有一个线程,那么同一个方法在同一时间只有一个调用者,也就不会存在所谓的死锁现象。js里面最多会出现死循环的现象。

    js单线程实现定时器的原理(个人理解,术语可能不准确,仅以理解运行机制为主)。先看一张个人画的示意图,比较简陋,不要挑刺哦

从这张图片中js的执行过程是从A代码流中顺序执行,然后碰到异步操作代码(setTimeout属于异步代码)就把这段代码扔到B这个堆栈中(堆栈是什么我自己也不太清楚,非计算机专业出身,我就把他当成一个整理箱,放了好几层东西),然后就不管他了,继续执行下面的代码,直到所有的非异步代码执行完毕后,js解释器才会去看B里面存的东西,然后逐一检查,看看哪个到时间点了,就拿出来执行,像上面我们写的0毫秒后执行,在检查中就会立马拿出来执行。

这个在顺序代码执行完毕后,js解释器检查B箱子中的代码是采用的轮询的形式,也就是每隔一段时间去检查一次,具体隔多长时间就不清楚了,这个相信各个浏览器相隔的时间间隔也不相同的。这样我们理解起来就很容易了,并不像我们想象中的setTimeout到时间了会很神奇的自己执行代码。

    对于到时间后就会执行某些代码这种功能我记得好像只有操作系统的中断机制可以做到吧。也不知道这句话对不对,专业人士勿喷哦。有愿意指点的可以发mooshineLove@163.com进行指正。

    现在我们再看上面那段代码,这个oo虽然是0毫秒后执行,但也是在所有非异步代码执行完毕后才后执行的。所以他是在nn之后才打印出来的。

    可能有人会问js中的script标签不是分块进行解析执行的么,那么上一块中的0毫秒执行是否在下一块的非异步代码之前呢。我可以明确的回答,异步代码是在所有的页面中的js非异步代码之后执行的。也就是说堆栈中的异步代码是在说有script标签中的非异步代码执行完毕后才会去执行的。

<script>
    function calltest(){
        console.log("mm");
        setTimeout(function(){
            console.log("oo");
        },0);
        console.log("nn");
    }
    calltest();
    console.log("ss");
</script>
<script>
	console.log("ww");
</script>


为了验证上面我所说了,这段代码的执行结果如下:

这个执行结果根据js的执行机制正是我们想要的,如果电脑慢一点的话,你还可以明显的看到oo的打印比其他的打印要慢一点出来,第一步先出来上面的打印,过不到1秒时间出来了oo。这个是我在chrome浏览器下的测试结果。




原创文章,转载请注明来自:妹纸前端-www.webfront-js.com.
阅读(3312)
辛苦了,打赏喝个咖啡
微信
支付宝
妹纸前端
妹纸前端工作室 | 文章不断更新中
京ICP备16005385号-1