许多最高级后端复试者会碰到某头条新闻如下表所示复试难题:
接着wlzwyyan的复试者就满脸幼稚地盼望你踩坑。只不过很单纯,var a 在那段标识符里多于两个,而 setTimeout 是该事件循环式非堵塞,因而等 a 全盘自赠完之后才继续执行 setTimeout,那这时 a 是 10,所以标准答案总之是 10 个 10。
假如你答错了,复试者又会问,假如想列印 0 到 9 你如果咋办,你说要用 let。
你去玩游戏查其原因,很多昌明里头写 let 建立的是块级返回值表达式,接着就没Nenon了 —— 不对形式系统展开说明的犯罪行为等同于耍流氓。这首诗是为的是帮你认知甚么是块级表达式。
例一
他们写两个范例:
在那段标识符中,{}形成了两个块,块里头的 a 和块外面的 a 互不干扰,也是说,a 有两个,里头两个,外面两个。console.log 将会列印 1。但假如你把上例中的 let 改成 var
这时输出 2。这是因为自始至终 a 这个表达式多于 1 个,赋值了 2,之前的那个 1 就不复存在了。上面那段标识符和下面那段本质是一样的。
例二
请问第二个块能正常输出 a 吗?标准答案是不能,a = 1 只在第两个块有效,第二个块没任何表达式,因而会输出 uncaught referenceError。
但是,他们用 var 来替代 let,console 是可以正常输出的,因为 var 是全局表达式,哪个块都可以拿到。
至此,他们回到那个wlzwyyan很喜欢考的复试题:
那段标识符是啥意思,意思是 a 始终都多于两个,setTimeout 输出时会输出最后那一时刻 a 的值,显然,所有的 setTimeout 会输出同两个值,你先别管是几。
但是,
的意思是,for 后面的每两个块都有两个 a,也是说,setTimeout 继续执行时,要去 for 形成的 10 个块分别去找属于那个块的 a 的值(在这两个过程中,因为有 setTimeout 对 a 的引用,a 不会被 GC 回收),因而,列印的是 0 到 9。
希望本文能让你认知清楚。