Eslint规则下 switch case 里面声明变量会报错的问题
export default {
mounted() {
this.test(9);
},
methods: {
test(param) {
switch (param) {
case 1:
break;
default:
let a = 1;
let b = 2;
console.log(a + b);
break;
}
},
},
};
这里会报错 之前一直没有遇到因为项目没有安装eslint,查询官方文档发现eslint规则no-case-declarations
配置文件 中的 "extends": "eslint:recommended"
属性启用了该规则
以下引用为[eslint中文文档](no-case-declarations - ESLint 中文文档 (nodejs.cn))
该规则该规则不允许在 case
/default
子句中使用词法声明(let
、const
、function
和 class
)。原因是词法声明在整个 switch 块中是可见的,但它仅在分配时才被初始化,只有在达到定义它的情况下才会发生。
为确保词法声明仅适用于当前 case 子句,请将您的子句包装在块中。
该规则旨在防止访问未初始化的词法绑定以及跨案例子句访问提升的函数。
正确写法应该是将所有的case和default都用{}包裹起来,
/*eslint no-case-declarations: "error"*/
/*eslint-env es6*/
// Declarations outside switch-statements are valid
const a = 0;
switch (foo) {
// The following case clauses are wrapped into blocks using brackets
case 1: {
let x = 1;
break;
}
case 2: {
const y = 2;
break;
}
case 3: {
function f() {}
break;
}
case 4:
// Declarations using var without brackets are valid due to function-scope hoisting
var z = 4;
break;
default: {
class C {}
}
}
何时不使用:
如果您依赖于失败行为并希望访问 case 块中引入的绑定。
js变量的提升影响
当然我很奇怪为什么有这样奇怪的规定,于是查询chat-gpt
,是因为**js
变量声明的变量提升**,之前一直以为js
只有var
才会存在变量提升,没想到let
和const
也有变量提升,但它们的行为有所不同。
-
var 声明的变量提升
- 使用
var
声明的变量会被提升到其所在函数的顶部(函数作用域内)或全局作用域的顶部(全局作用域内)。 - 提升后的变量会被赋予默认值
undefined
,但它们的赋值操作会留在原来的位置,直到代码执行到这里时才会执行赋值操作。
console.log(x); // undefined var x = 10; console.log(x); // 10
- 使用
-
let 和 const 声明的变量提升
- 使用
let
或const
声明的变量也会被提升,但与var
不同,它们并不会被赋予默认值,而是在提升阶段形成一个“暂时性死区”(Temporal Dead Zone,简称 TDZ)。 - 在 TDZ 中,如果尝试访问这些变量,会导致 ReferenceError 错误。
console.log(x); // ReferenceError: Cannot access 'x' before initialization let x = 10; console.log(x); // 10
因此,尽管
let
和const
声明的变量也会发生变量提升,但它们有一个暂时性死区的概念,不允许在声明前访问它们,这是为了避免在变量未初始化的情况下使用变量,从而增强代码的可靠性和安全性。switch case的每个case不是一个单独的作用域吗?
- 使用
JavaScript 中的 switch
语句并不会创建新的作用域,每个 case
分支内声明的变量会被提升到 switch
语句所在的作用域中,因此可能会导致变量提升带来的问题。
举个例子来说,考虑以下代码:
switch (value) {
case 1:
let x = 10;
console.log(x);
break;
case 2:
let x = 20; // 这里会报错,因为在同一个作用域内重复声明了变量 x
console.log(x);
break;
default:
console.log('default');
}
在这个例子中,虽然每个 case
内部看起来像是一个独立的块,但实际上它们都属于同一个 switch
语句的作用域。因此,第二个 case
中的 let x = 20;
会与第一个 case
中的 let x = 10;
冲突,导致语法错误。
为了避免这种情况,可以使用花括号 {}
创建一个新的块级作用域,从而确保每个 case
中的变量声明不会互相干扰,也不会导致变量提升带来的问题。