块级函数
先来看一道极具迷惑性的面试题
1
2
3
4
5
6
7
8var a;
if(true){
a=5;
function a(){}
a=0;
console.log(a)
}
console.log(a)你可能会以为答案是
0 0
事实上,答案是0 5
来看一下stackoverflow的解释
这段代码在浏览器中是这么工作的1
2
3
4
5
6
7
8
9var 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变量
- 进入块作用域
function a(){}
被提升至块作用域顶部- 执行
a=5
- 块作用域里的a被赋值为5,
function a
被覆盖 - 执行到
function a(){}
,ES6块作用域中的函数a(现在已经被赋值为5)被提升至块外最顶部,外部变量a被映射为块内a的值5 - 此时块内a为5,因此外部的a也为5
a=0
,块内的a被赋值为0,外部的不再受影响- 块内打印a,打印0
- 离开块作用域,此时块内对块外为不可见状态
- 打印外部变量a,此时外部a为5,因此打印5
- debug实验
- 在MDN官方文档中,对这种非严格模式下的块级函数声明作了解释,官方建议不要使用这种形式的函数定义,因为代码执行过程在不同的浏览器中是不同的,如果需要条件定义函数,推荐采用以下形式
1
2
3
4
5let fn=null;
if(condition){
fn=function(){}
}
fn&&fn(); - 相关链接
- https://github.com/lizhongzhen11/lizz-blog/issues/98
- https://262.ecma-international.org/6.0/#sec-block-level-function-declarations-web-legacy-compatibility-semantics
- https://stackoverflow.com/questions/31419897/what-are-the-precise-semantics-of-block-level-functions-in-es6
- https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions