块级作用域内的函数声明到底是什么???
程序员文章站
2022-06-17 18:53:00
...
说明
在一篇文章里看到这样一个问题。文章地址
文章中会扩展一些其他的内容, 大家可以看过之后再来看我这篇个人的总结
函数声明写在块级作用域中(ES6)
var a = 0;
if(true){
a = 1;
function a(){}
a = 21;
console.log("里面",a);
}
console.log("外部",a);
请问输出是什么? 答案是:里面21 外面1。
正如我一样,看到答案的我蒙蔽了,然后就继续阅读完全文,感觉还是有点不太明白。最后经过我查询资料我得到了答案。
转换结果
代码转化如下:
var a;
var a = 0;
if (true) {
let a = function a() {
}
a = 1;
window.a = a; //此处为原函数声明的位置
a = 21;
console.log("里面",a);
}
console.log("外部",a);
其实,函数声明放在块级作用域内做了以下几件事。
so, 我想看到了转换后的代码,估计大家就豁然开朗了。
-
{}内部修改的是let定义的块级a,跟外部没关系。
-
所以 a = 1 的时候,外部其实还是为0。
-
外部的全局a原本为0, 被window.a = a 同步为了1.
-
a =21 块级a变成了21,全局a无变化还是1.
那么为啥会这么转换呢???
实质
-
函数声明会被提升到块级作用域顶部。
-
使用了类似let的方式定义了一个块级作用域的函数同名变量,并赋值。(个人总结)
-
函数声明的变量被声明到了全局作用域(或者函数作用域)顶部。
-
在函数声明的位置,会将目前块级作用域内的变量的值,同步到全局作用域(函数作用域)下。
解释
如下标记 1234 ,我想这样是最直观的。
(window 代表的外层的作用域上下文,意思是if块所在的作用域,因为此处为全局,所以为window)。
var a; // 3
var a = 0;
if (true) {
let a = function a() {
// 1,2
}
a = 1;
window.a = a; // 4:此处为原函数声明的位置
a = 21;
console.log("里面",a);
}
console.log("外部",a);
扩展
if(true) {
function a( ){}
}
转换为es5为
"use strict";
if (true) {
var a = function a() {};
}
所以经过我的查找,所有人都不推荐直接在块级作用域内进行函数声明,如果非要,就请使用es5的函数表达式写法。