从settimeout看javascript的运行机制

媒介

我们晓得JS是一个单线程的言语,而且其运转机制比较特别。
下面我们经由过程settimeout的几个示例来展示javascript的运转机制的特别点

示例1

console.log(1);
setTimeout(function(){
    console.log(2);
},0);
console.log(3);
// 打印出 1 3 2

示例2

console.log('1');
setTimeout(function(){
    console.log('2');
},0);
while(1){}
// 打印出1,然后浏览器卡死,不会打印出2

javascript会先把须要运转的内容放到使命行列中
然则假如碰到settimeout,会以为这是个异步使命,会先放到异步行列中
浏览器会先实行同步使命,比及同步使命实行完以后,再检察异步行列
假如异步行列中的使命的实行机遇到了,浏览器就会把使命放到同步行列中去。

即:
异步使命肯定在同步使命以后实行。

示例3

for(var i = 0; i < 4; i++){
    setTimeout(function() {
        console.log(i);
    }, 1000);
}
// 打印 4 4 4 4

为何打印出的是4 4 4 4呢?
由于浏览器会先实行for轮回
每实行一次for轮回,都把一个settimeout压入异步行列
1000毫秒以后,实行settimeout里的要领的时刻,i的值已经是4了。

假如要打印0 1 2 3怎么办呢?
应用闭包的特征,把i缓存到一个temp值里

for(var i = 0; i < 4; i++){
    (function(temp){
        setTimeout(function() {
            console.log(temp);
        }, 1000);
    })(i);
}
// 打印 0 1 2 3

如许做等于是每一次for轮回都新建了一个匿名函数,i的值被存入了这个匿名函数的内存里。
明白了闭包的同砚肯定能够明白这一点。

示例4

我们晓得ES6引入了新的关键字let
在这里,let有一个新的特征

for(let i = 0; i < 4; i ++){
    setTimeout(function(){
        console.log(i); 
    }, 1000);
}
// 打印 0 1 2 3

示例4与示例3只要var和let这个处所有区分,然则打印出来的效果却完整差别
这是由于let是一个块级作用域
let定义的i,关于每个for轮回的实行来讲都是一个全新的i(运用差别的内存地址)
所以打印的时刻能够获得0 1 2 3

    原文作者:aaron_lawliet
    原文地址: https://segmentfault.com/a/1190000019135774
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞