js执行机制经典面试题(一)

经典面试题

如果你知道以下代码输出结果,出门左拐,不送,如果你不懂,你需要认认真真的看。
process.nextTick必须在nodejs中执行

 console.log('1');

    setTimeout(function() {
        console.log('2');
        process.nextTick(function() {
            console.log('3');
        })
        new Promise(function(resolve) {
            console.log('4');
            resolve();
        }).then(function() {
            console.log('5')
        })
    })
    process.nextTick(function() {
        console.log('6');
    })
    async function fn() {
        await fn2();
        console.log(13);
    }

    function fn2() {
        console.log(14);
    }
    fn()
    new Promise(function(resolve) {
        console.log('7');
        resolve();
    }).then(function() {
        console.log('8')
    })

    setTimeout(function() {
        console.log('9');
        process.nextTick(function() {
            console.log('10');
        })
        new Promise(function(resolve) {
            console.log('11');
            resolve();
        }).then(function() {
            console.log('12')
        })
    })

javascript事件循环

既然js是单线程,那就像只有一个窗口的银行,客户需要排队一个一个办理业务,同理js任务也要一个一个顺序执行。如果一个任务耗时过长,那么后一个任务也必须等着。那么问题来了,假如我们想浏览新闻,但是新闻包含的超清图片加载很慢,难道我们的网页要一直卡着直到图片完全显示出来?因此聪明的程序员将任务分为两类:
同步任务
异步任务

同步任务和异步任务

你以为的js是不是下边这样。123

  console.log(1);
        setTimeout(() => {
            console.log(2);
        }0)
        console.log(3);

你错了 ,他的结果是132;
首先你要明白什么是同步和异步。

同步

大家都知道js代码从上而下执行,同步的操作有以下几个

  1. console.log语句
  2. 函数声明
  3. 函数调用
  4. 实例化对象;
  5. 但是需要记住.promptconfirmalert都会阻塞代码的执行。
    阻塞不是异步是直接中断代码的执行。
    在这里插入图片描述

在这里插入图片描述

异步操作

异步操作会等待所有的同步操作执行完成以后才会执行异步操作

我们进入正题,除了广义的同步任务和异步任务,我们对任务有更精细的定义:

macro-task(宏任务):包括整体代码scriptsetTimeoutsetInterval
micro-task(微任务):Promiseprocess.nextTick ,await

分析面试题

 console.log('开启成功');
    console.log('1');
    setTimeout(function() {
        console.log('2');
        process.nextTick(function() {
            console.log('3');
        })
        new Promise(function(resolve) {
            console.log('4');
            resolve();
        }).then(function() {
            console.log('5')
        })
    })
    process.nextTick(function() {
        console.log('6');
    })
    async function fn() {
        await fn2();
        console.log(13);
    }

    function fn2() {
        console.log(14);
    }
    fn()
    new Promise(function(resolve) {
        console.log('7');
        resolve();
    }).then(function() {
        console.log('8')
    })

    setTimeout(function() {
        console.log('9');
        process.nextTick(function() {
            console.log('10');
        })
        new Promise(function(resolve) {
            console.log('11');
            resolve();
        }).then(function() {
            console.log('12')
        })
    })
  1. 找出所有的同步操作和异步操作
 console.log('1');

刚才说过,调用函数也属于同步,所有调用了fn()
执行

async function fn() {
        await fn2();
        console.log(13);
    }

因为fn属于async函数,所以会先执行await这一行的代码,但不会async函数中的await下一行的代码
所以执行调用fn2执行

 console.log(14);

然后执行promise实例化对象中的

 console.log('7');

此时此刻都属于同步操作

  1. 执行异步操作

异步分为宏任务与微任务

setTimeout宏任务放到最后执行

现在其中有三个微任务

 process.nextTick(function() {
            console.log('6');
        })
  async function fn() {
        await fn2();
        console.log(13);
    }
.then(function() {
        console.log('8')
    })

按照代码执行的先后顺序,先执行

 console.log('6');

因为fn()的函数调用在实例化promise之前,所以先执行

 console.log(13);

最后执行

 console.log('8')

此时此刻微任务执行完毕。
然后是两个计时器宏任务

 setTimeout(function() {
        console.log('2');
        process.nextTick(function() {
            console.log('3');
        })
        new Promise(function(resolve) {
            console.log('4');
            resolve();
        }).then(function() {
            console.log('5')
        })
    })

还是一样的逻辑
上面的输出 2 ,4在计时器中属于同步,先执行。
然后执行微任务 3,5

面试题输出结果为

1 14 7 6 13 8 2 4 3 5 9 11 10 12

在这里插入图片描述
fn()放在实例化promise之后你还会吗.

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值