从一道诡异的JS面试题说“作用域”与“提升”

开发 前端
有朋友问我一道面试题:一道考察“Hoisting"的面试题目,本篇就这个问题和大家一起学习探讨一下!

[[392744]]

 “面试造火箭,工作拧螺丝”。面试题目之诡异,常令人匪夷所思。试看一道考察“Hoisting"的面试题目:

一、提升全局变量 var

  1. var tmp = new Date(); 
  2.  
  3. function f() { 
  4.     console.log(tmp); 
  5.     if (false) { 
  6.         var tmp = "hello"
  7.     } 
  8. f(); 

JS新手往往会以为将正常打印出日期,而实际输出的确是`undefined`!

  1. > var tmp = new Date(); 
  2. function f() { 
  3. ...     console.log(tmp); 
  4. ...     if (false) { 
  5. .....         var tmp = "hello"
  6. .....     } 
  7. ... } 
  8. > f(); 
  9. undefined  

这是因为在函数f()的内部,var被提升到定义域的顶部,实际执行为:

  1. var tmp = new Date(); 
  2.  
  3. function f() { 
  4.     var tmp;// 提升到这里,将全局的tmp覆盖了。var默认赋值为undefined 
  5.     console.log(tmp); 
  6.     if (false) { 
  7.         var tmp = "hello"
  8.     } 
  9. f(); 

也就是说var不仅提升,而且将tmp初始化赋值为undefined。

二、如何才能正常输入日期呢?

解决方案是将global-scope的var替换为block-scope的let:

  1. var tmp = new Date(); 
  2.  
  3. function f() { 
  4.     //var tmp;// 提升到这里,将全局的tmp覆盖了。var默认赋值为undefined 
  5.     console.log(tmp); 
  6.     if (false) { 
  7.         let tmp = "hello"
  8.     } 
  9. f(); 
  10. // 2021-04-02T10:52:30.983Z 

这是因为let定义的是local-variable.

三、TDZ临时DeadZones

更加诡异的案例,来单独看let:

  1. var tmp = new Date(); 
  2.  
  3. function f() { 
  4.     console.log(tmp); 
  5.     let tmp = "hello"
  6.  
  7. f(); 

你原以为将会如常打印出时间,但却报错tmp未定义。

  1. ReferenceError: Cannot access 'tmp' before initialization 

这是因为 tmp 被提升,其实际执行为:

  1. var tmp = new Date(); 
  2.  
  3. function f() { 
  4.     let tmp; // 提升在这里 
  5.     console.log(tmp); 
  6.     let tmp = "hello"
  7.  
  8. f(); 

然而区别于var的是,tmp仅仅被提升,却不会被自动赋值为undefined,因此会报错`ReferenceError`.

该问题就是传说中的TDZ (temporal dead zone)。解决方案也简单,就是将所有的let或者const等全部都写到最上面。

 

责任编辑:姜华 来源: 今日头条
相关推荐

2021-03-27 10:59:45

JavaScript开发代码

2024-10-11 17:09:27

2018-04-26 11:23:01

Linuxfork程序

2011-05-23 11:27:32

面试题面试java

2022-02-08 18:09:20

JS引擎解析器

2018-03-06 15:30:47

Java面试题

2009-08-11 10:12:07

C#算法

2023-02-04 18:24:10

SeataJava业务

2009-08-11 14:59:57

一道面试题C#算法

2021-05-31 07:55:44

smartRepeatJavaScript函数

2009-08-11 15:09:44

一道面试题C#算法

2017-11-21 12:15:27

数据库面试题SQL

2022-04-08 07:52:17

CSS面试题HTML

2023-08-01 08:10:46

内存缓存

2021-03-16 05:44:26

JVM面试题运行时数据

2021-10-28 11:40:58

回文链表面试题数据结构

2020-11-06 09:05:18

前端web开发

2017-03-10 09:33:16

JavaScript类型

2015-09-02 14:09:19

面试题程序设计

2011-03-02 10:58:16

SQL server入门面试题
点赞
收藏

51CTO技术栈公众号