如何理解switch case块中函数声明的特殊行为?
JavaScript中switch语句内函数声明的作用域行为解析
第一种情况:仅未执行分支中有函数声明
先看这段代码:
switch (0) { case 0: console.log("Case 0 started"); foo(); console.log("Case 0 ended"); break; case 1: function foo() { console.log("foo is a function") } break; } console.log("But here foo is:", foo); foo();
现象:即便case 1永远不会执行,foo()在case 0中能正常调用,但顶层作用域里foo是undefined,调用时会报错。
第二种情况:执行分支中添加同名函数声明
修改后的代码:
switch (0) { case 0: console.log("Case 0 started"); // Add this declaration. function foo() { } foo(); console.log("Case 0 ended"); break; case 1: function foo() { console.log("foo is a function") } break; } console.log("But here foo is:", foo); foo();
现象:顶层作用域中可以正常访问foo,调用不会报错。
行为原理
这是由ECMAScript标准中块级作用域内函数声明的特殊处理规则导致的:
- 在非严格模式下,块级作用域(整个
switch属于一个块)内的函数声明,会在包含该块的外层作用域(这里是全局作用域)中创建变量绑定,但绑定的初始化会推迟到代码执行到函数声明的位置时。 - 第一个例子里,
case 1的foo声明虽被提升到switch块顶部(所以块内case 0能调用foo),但由于case 1从未执行,函数初始化步骤未完成,外层作用域的foo始终是undefined。 - 第二个例子里,
case 0的foo声明被执行到,完成了函数初始化,外层作用域的foo绑定被赋值为该函数,因此顶层可正常访问。
另外要注意:switch的所有case分支属于同一个块作用域,不同分支的同名函数声明会共享同一个外层绑定。
规范参考
根据ECMAScript 2015(ES6)及后续版本规范:
- 非严格模式下,块内函数声明会被提升到外层函数/全局作用域,但初始化仍在块内声明位置执行。
- 严格模式下,块内函数声明的作用域被限制在块内部,外层无法访问,不会出现上述跨块绑定行为。
内容的提问来源于stack exchange,提问作者krave
相关产品推荐
相关产品推荐

