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

 “面试造火箭,工作拧螺丝”。面试题目之诡异,常令人匪夷所思。试看一道考察“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等全部都写到最上面。

分享文章:从一道诡异的JS面试题说“作用域”与“提升”
文章分享:http://www.shufengxianlan.com/qtweb/news25/434825.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联