JS的执行机制

JS的执行机制

我觉得如果要说JS的执行机制,先来一道经典的面试题吧。这道题先放在这里一会回来解答

 for(var i = 0; i < 5; i++) {
    setTimeout(function(){
        console.log(i);
    },1000)
 }

 JavaScript语言的一大特点就是单线程。也就是说同一时间只能做一件事。这是因为JavaScript这门简本语言诞生的使命所导致——JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个元素进行添加和删除操作,不能同时进行。

 

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
这样所导致的问题是: 如果 JS 执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。

 

为了解决JS单线程的问题JS中出现了同步任务和异步任务

同步

前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟之后),再去切菜,炒菜。

 

异步

你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。

 

同步和异步的本质区别:这条流水线上的各个流程的执行顺序不同。比如我不再需要等待水烧开了再去炒菜了,会大大节省时间,增加效率。

 

JS中所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。

同步任务指的是:
在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;


异步任务指的是:
不进入主线程、而进入”任务队列”的任务,当主线程中的任务运行完了,才会从”任务队列”取出异步任务放入主线程执行。

 

 

 JS事件执行机制(事件循环)

 

 

 

 

 由于主线程不断重复地获得任务、执行任务、在获得任务、在执行。这种执行机制称为事件循环。

 

再来看前面那道题

1.等执行栈内地同步地for循环执行结束出栈后,线程才会从任务队列里拉取异步地定时器地回调函数

 

for(var i = 0; i < 5; i++) {
   console.log(i);

 
    setTimeout(function(){
        console.log(i);
    },1000)
 }
//先输出1234;在输出5个5

 

2.尽管循环中的五个函数是在各个迭代中分别定义地,但是他们都被封闭在一个共享地全局作用域中,因此实际上只有一个i

 解决办法:

1.ES6 使用let声明变量。使用let声明地变量具有块级作用域,这样每次每次迭代都会在声明一次。

2.闭包。使用闭包地时候要注意添加自己地变量。因为不添加自己的变量,回调函数引用地还是那个唯一的变量i。

 

最后送给大家一道题目,感兴趣的可以试试。

console.log('start');

        setTimeout(function () {
            console.log('你猜我输出在哪');
        }, 0);

        console.log('end');

        for (var i = 0; i < 10; i++) {
            console.log(i);
        }
        // console.log('-----------------------');

        console.log('start');
        
        for (var i = 0; i < 3; i++) {
            (function (index) {
                setTimeout(function () {
                console.log(index);
                }, 0);
            })(i);
        }
        console.log('end');

 

posted @ 2020-09-17 11:14  mingshen123  阅读(132)  评论(0)    收藏  举报