JavaScript中if代码块内变量与函数的作用域相关问题
问题原因解析
这个报错是块级作用域内函数声明的特殊提升规则导致的,核心逻辑如下:
基础规则铺垫
var声明不存在块级作用域,声明会提升到所属函数/全局作用域顶部,赋值逻辑留在原位置,这也是你第一个测试代码块变量能在块外访问的原因。- 普通的全局/函数内的函数声明,会将完整的函数体提升到作用域顶部,因此可以在声明位置之前正常调用。
- 但块级作用域(
if/for等的{}内部)中的函数声明,在ES6规范中做了兼容处理,行为类似var:- 函数名会作为变量提升到外层作用域(本案例中是全局作用域)顶部,默认值为
undefined - 完整的函数体赋值,仅会提升到块级作用域的顶部
- 当代码执行到块内函数声明的位置时,才会将块内定义的函数同步赋值给外层作用域的同名变量
- 函数名会作为变量提升到外层作用域(本案例中是全局作用域)顶部,默认值为
三个代码块的行为对应
- 第一个
var测试的表现和你观察的一致,符合var的提升规则。 - 第二个代码块可以正常执行:你首次调用
sayHello是在if块内部,进入块作用域后函数已经完成块内提升,因此可以正常调用;if块执行完成后,全局的sayHello已经被赋值为函数,所以块外调用也正常。 - 第三个代码块报错的原因:你在进入
if块之前就调用了sayHello,此时全局作用域的sayHello还只是被提升声明的undefined,不是函数,因此调用直接抛出TypeError。
规避建议
尽量不要在块级作用域内使用函数声明,如果需要块内的函数逻辑,优先使用const/let声明的函数表达式,避免出现预期外的提升问题。
内容的提问来源于stack exchange,提问作者Paras Bisht
相关产品推荐
相关产品推荐

