一道关于JS执行机制的面试题

本文通过一道面试题探讨JavaScript执行机制,涉及this指向、自增运算符、定时器原理、微任务与宏任务、箭头函数的this绑定以及Promise的异步行为。分析了题目中可能出现的输出情况,并指出定时器的精度问题,引导深入讨论JS的单线程、事件循环等相关概念。
摘要由CSDN通过智能技术生成

今晚在掘金大佬的文章里看到一道题,稍加改造,并有点自己的浅见可以记录一下。

大佬的文章 https://juejin.im/post/5eb55ceb6fb9a0436748297d ,题就是那照片中的第3题。

我稍加改造,加入了 Promise ,以体现 微任务和宏任务 的知识点。

function Counter() {
    var start = Date.now();
    this.num = 0;

    this.timer1 = setInterval(function() {
        this.num++;
        var gap = Date.now() - start;
        Promise.resolve(2020).then(res => {
            this.num++;
            gap -= res;
        })
        console.log('timer1', this.num, gap);
    }, 996);

    JSON.parse('{"desc":"...."}'); // 假设解析耗时 1024 毫秒

    this.timer2 = setTimeout(() => {
        this.num++;
        var gap = Date.now() - start;
        Promise.resolve(2020).then(function (res) {
            this.num++;
            gap -= res;
        })
        console.log('timer2', this.num, gap);
    }, 0);
}

new Counter(); // 写出前 10 条输出

// Counter(); // 如果直接调用呢? 也写出前 10 条输出

了解JS执行机制的话,这题不难吧。大概的有哪些坑,我列一下:

  • this指向,这个真是 “逢面必考” 哇
  • 自增自减运算符,其实相当于 a = a + 1 ,本质还是赋值,所以可以执行,同时涉及到数据类型的隐式转换。
  • 定时器函数是同步执行的,但是其回调函数是推入 Event Table ,等到时间到了,就推入 Event Queue ,再要等到主线程空闲,事件轮询机制才把它拿到主线程去执行。
  • setInterval() 不是重复执行,而是每隔所设定的时间,就生成一个回调,推入事件队列,每次回调里的变量都是新的。同时,第一次回调的执行也是在等待设定的时间之后的,不要搞混。哦,还有,如果主线程一直没空,那么 setInterval() 可不管,默默地一直往事件队列里推入回调,所以很可能,等主线程有空了,Event Queue 里已经堆满了它的回调,哈哈哈哈
  • 然后是箭头函数,它内部不绑定 this ,而是使用 它定义时的 上下文this,所以不管你之后是在哪调用,它内部的 this 还是要往它定义时的作用域里找,其实就是说创建这个箭头函数的地方,我们创建函数一般是不会写 new Function() 的,所以要理解写字面量的 () => {} 这就是创建了一个函数实例对象。题中 setTimeout() 里的箭头函数回调,是在什么时候创建的呢?当然是 Counter() 被调用被执行的时候咯,所以 this 指向就不用多说了吧。
  • 再然后就是我自己加了个 Promise ,主要是需要注意 .then() 里的回调也是异步的哦,而且是微任务。微任务就是宏任务拿到主线程执行完了,顺便也把同一个作用域内的微任务执行掉,就像吃大餐吃饱了,其实还可以再扒几口饭后甜点的,哈哈。。。对了,还要看到里面箭头函数跟普通匿名函数的区别,注意 this 指向哦。
  • 最后,还有 996 + 1024 = 2020 ,不能错过哦,哈哈

最后再记录一下个人的一点浅见。如果我是面试官,可能会觉得这题能分三层:

  • 搞不清楚 this 指向,或者认为 this.num++gap -= res 会报错的,在第一层,直接pass
  • 完整写出 10 条输出的,在第二层
  • 写出 3~5 条输出就不写了的,更有意思,哈哈

为什么呢?因为 写出 3~5 条输出后,后面就都是按规律重复而已。这时候应该 向面试官解释为什么不写完10条:因为 定时器是不准的,gap 的值 会有 几个毫秒 的误差,每次执行都不一定保证结果一致。

然后就可以跟面试官扯一扯为什么定时器不准呢?因为 JS 是脚本语言,边解释边执行,而且是单线程的,异步任务会被推入异步队列,然后定时器的回调是异步任务里的宏任务,每次都要等到下一个 Event Loop 里,再被拿出来执行,而每个 Event Loop 消耗的时间可能是零点几毫秒,也可能是一两个毫秒,要看执行环境,所以,gap 的值每次都会有一点点误差。

最后再深入聊一聊 单线程、微任务和宏任务、事件队列、事件轮询机制、Event Loop ,等等,那跟面试官的PY不就好啦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值