昨天个人一个技术交流群里发了一段代码,涉及的是变量和函数的声明提高,执行结果很是让人迷惑,你们讨论许久,仍是有地方解释不清楚,到最后,仍是发布到stack overflow
,经过大佬解惑才弄明白,这里我再整理一下。javascript
逐个解析一下讨论到的案例:html
没有特别说明的,运行环境就是是chrome77。
var a if(true) { a = 5 function a() {} a = 0 console.log(a) } console.log(a)
先整理一下个人思路:java
变量a
声明;if语句块
,是一个块级做用域;变量a
的赋值,还声明了一个函数a
。按照声明提高原则,函数a
声明会被提高,这里没有使用let
、const
,因此我按ES5
以前的声明提高规则去分析的。es6
没有块级做用域,提高到全局,并且函数声明优先于变量声明,因此会覆盖变量a的声明。web
那么答案是:chrome
0 0
很遗憾,这个答案是错的,至少现代浏览器是错的(我后来在IE的模拟环境运行,确实是这个结果)。浏览器
如今,公布一下正确答案:函数
0 5
这个答案很是让人疑惑不解:code
第二个输出5,究竟是怎么回事?htm
let a = function(){}
,那么a=5
是暂时性死区;var a = function(){}
,那么会和上面同样,输出0 0
;先看看代码运行解析[引用1],咱们能够把代码运行当作这样:
var a¹; if (true) { function a²() {} // hoisted a² = 5; a¹ = a²; // at the location of the declaration, the variable leaves the block a² = 0; console.log(a²) } console.log(a¹);
解释一下:
变量a
声明,这里没有问题。函数a
声明提高,提高到块级域顶部。a=5
,这里赋值的对象是本地的函数a
,覆盖了。函数a
声明处,本地的变量a
覆盖了全局的变量a
。按照[引用2]解释,这里也是提高,也就是说函数a
声明提高了两次。到这里疑惑终于解开了!这里要说明两点:
ES5
中是非法的,在ES6
中并无严格规定(考虑到向下兼容性,参考阮老师的ES6入门),也就是这块依赖于实现[引用3]。](https://stackoverflow.com/que...