一道js题目引起我对var作用域和事件队列的强烈反思

145 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

前言

今天没有写博客没有什么思路,于是决定去刷下面试题,做一个题目解析.
错题如下:

微信图片_20221002191249.jpg

1.首次错误思路

我的解题思路(错误)

  • 1.外层一个for循环,初始值i为0,i<5,
    • 循环次数:五次,
    • i的值依次为:0,1,2,3,4
    • i最后在循环外为5
  • 2.内层有一个requestAnimationFrame()函数,
    • requestAnimationFrame()函数包了一个箭头函数,箭头函数是logi的值
    • 箭头函数是控制台打印i的值
  • 3.首先i再循环中的值依次为0,1,2,3,4
    • requestAnimationFrame()我不认识,直接忽略他了,直接当成控制台输出i的值了
    • 所以我的答案是B:0,1,2,3,4

image.png

2.本题正确思路

  • 1.外层一个for循环,初始值i为0,i<5,
    • 循环次数:五次,
    • i的值依次为:0,1,2,3,4
    • i最后在循环外为5
    • 但是由于这里使用的是var,var是全局作用域
    • 所以当循环退出时i为5,因此全局中的i都变为五
  • 2.内层有一个requestAnimationFrame()函数,
    • requestAnimationFrame()函数包了一个箭头函数,箭头函数是logi的值
    • 箭头函数是控制台打印i的值
    • requestAnimationFrame()是异步的宏任务,会在同步任务完成后执行
  • 3.执行顺序为先同步后异步
    • 首先执行同步任务for循环
    • 同时由于使用的是var定义i是全局变量,在最后的i变为5后,所有的i都变为5
    • 第二同步任务执行完毕后,执行异步任务requestAnimationFrame(()=>console.log(i))
    • 此时i都为5
    • 所以答案为D:5,5,5,5,5

image.png

3.反思

3.1对于不认识的函数直接当不存在导致错误

虽然我不认识requestAnimationFrame(),但是可以看出,这个函数里面包了一个回调函数,可以初步推断是一个异步队列

3.2看到var没有敏锐的想到var和let作用域的区别导致错误

4.总结

4.1let和var区别

  • 作用域不同:
    • var是全局作用域,声明的变量是全局变量,容易被污染,最后的i变了,之前的i也会变
    • let是块级作用域,声明的变量是块级变量,不易被污染,每次for循环都会生成一个块级作用域,最后的i变了,之前的i不会变

4.2requestAnimationFrame()函数

作用:

  • window.requestAnimationFrame()  告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

语法:


window.requestAnimationFrame(callback);

是否异步:

  • requestAnimationFrame异步宏任务

4.3解题方法

  • 要思考题目考察的是什么
  • 本题考察的是
    • 1.var作用域
    • 2.事件队列