【Q1】下面代码将会输出什么?为什么呢?

前几天看到一道题,差点颠覆之前所学,极度怀疑人生~~~

于是研究了一下,也请教了在前端领域工作好几年的小伙伴们,然而,出乎我意料是大伙也都很“荣幸”地答错了...嘿嘿,让我这个初出茅庐的小白心里或许有些小小“安慰”...其中有位前辈说这道题就算搞懂又咋样了,但,没办法骨子里带着一股韧劲想去学习研究其中“奥妙”。话不多说,上题。

乍一看,大伙们都不约而同地回答,输出都是10啊,然后问为何,就没有然后了......

如果你也认为输出都是10,那么“恭喜”你答错了!有趣吧,这其中的“奥妙”就在if语句块内声明函数,即有条件的创建函数(在不同浏览器中有不同的效果,本文讲解仅代表在当前版本chrome浏览器中的结果分析)。

如果去掉外层if语句,再来看题:

var d = 0;
//if(true){
  d = 1;
  function d(){}
  d = 10;
  console.log(d);
//}
console.log(d);

这时,毫无疑问都是输出 10 呢。可为何加上外层if语句就会有所不同,甚至给人诡异的感觉呢?

函数可以被有条件来声明,也就是说函数声明可能出现在一个 if 语句里。有的浏览器会将这种有条件的声明看成是无条件的声明,即是无论条件是true还是false,浏览器都会创建函数。因此,它们不应该被使用

但,大部分浏览器都没有遵守这个ES5标准,各浏览器JS引擎生产商不同,可以有自己的实现方式:

  • 允许在块级作用域内声明函数
  • 函数声明类似于var,即会变量提升到全局作用域或函数作用域的最顶端
  • 同时,函数声明还会提升到其所在块级作用域的最顶端

注意:以上3条规则只针对ES6浏览器实现有效,其他环境下的实现不用遵循,仍将块级作用域的函数声明作let处理即可。

如果对变量提升函数提升不是很清楚的童鞋,可以参看JavaScript:变量提升和函数提升

下面就将题目代码解析如下:

//块级作用域内的function d() {}类似于var ,会在全局作用域这里声明一个同名变量d,值为undefined
console.log("第1行:",window.d,d); //undefined  undefined
var d = 0;
if(true){
//function d() {}函数声明会提升到块级作用域最顶端
  console.log("第2行:",window.d,d); // 0  function d() {}(函数对象)
  d = 1;
  console.log("第3行:",window.d,d); // 0  1
  function d() {}  //执行到函数声明原始位置这一行,才会改变块级作用域外(全局作用域)的变量d。会将块作用域里的d赋值到全局同名变量d
  console.log("第4行:",window.d,d);  //1  1
  d = 10;
  console.log("第5行:",window.d,d);  //1  10
}
console.log("第6行:",window.d,d);   //1  1

总结

  • if 语句块内的函数声明首先会在块级作用域外(全局作用域)定义一个同名变量d ,并初始化赋值undefined;
  • if 语句块内的函数声明会提升到块级作用域最顶端
  • 执行到函数声明原始位置时,块级作用域内的函数变量名d的值赋值给外部同名变量d;
  • 由于各浏览器实现不同,不建议在if 语句块内使用函数声明式定义函数,可以使用函数表达式形式代替。

到此,这道题其中蕴含的“奥妙”想必也都能理解了哦,也不枉我花了时间对其的研究啊!还不能理解的小伙伴们,就多理解几遍看看呢,只要肯钻研学习,没什么学不会的哦!

如果你觉得这篇文章对你有帮助,请点赞支持一下哦!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
禁止转载,如需转载请通过简信或评论联系作者。

相关阅读更多精彩内容

友情链接更多精彩内容