最近在代码中不小心不范例的,在switch内里定义了块级变量,致使页面在某些浏览器中失足,本文议论以下switch语句中的块级作用域。
- switch语句中的块级作用域
- switch语句中的块级作用域能够存在的题目
- 范例和检测
本文的原文在我的博客中,https://github.com/forthealll…
迎接star
一、switch语句中的块级作用域
ES6 或 TS 引入了块级作用域,经由历程let和const、class等能够定义块级作用域里的变量,块级作用域内的变量不存在变量提拔,且存在暂时性死区。罕见的if语句,for轮回的轮回体内都能够定义块级变量。那末switch语句中的块级作用域是什么呢? 先给出结论:
switch语句中的块级作用域,在全部switch语句中,而不是关于每个case天生一个自力的块级作用域。
下面来举几个例子来申明这个题目:
let number = 1;
switch(number){
case 1:
let name = 'Jony';
default:
console.log(name)
}
上述的代码会输出jony。
再看一个例子:
let number = 1;
switch(number){
case 1:
let name = 'Jony';
break;
case 2:
let name = 'yu';
break;
default:
console.log(name);
}
如许会在反复性命的毛病:
Uncaught SyntaxError: Identifier 'name' has already been declared
上述两个例子申明白切switch语句中,全部switch语句组成一个块级作用域。而与case无关,每个case并不会组成一个自力的块级作用域。
二、switch语句中的块级作用域能够存在的题目
我们知道了switch语句,全部switch语句的顶层是一个块级作用域,然则还要注重case的特殊性,在case中声明的变量,并不会提拔到块级作用域中。
let number = 2;
switch(number){
case 2:
name = 'yu';
break;
}
在这个例子中,name虽然没有声明,然则给name赋值相当于给全局的window对象复制,也就是window.name = ‘yu’。不会有任何题目。
有意思的题目来了:
let number = 2;
switch(number){
case 1:
let name = 'jony';
break;
case 2:
name = 'yu';
break;
}
这个例子中,会报错,会报name未定义的毛病。
Uncaught ReferenceError: name is not defined
缘由的话,这里虽然case内里定义的块级虽然不会存在变量提拔,然则会存在暂时性死区,也就是说假如let name = ‘jony’ 没有实行,也就是name定义的历程没有实行,那末name在全部块级作用域内都是不可用的,都是undefined。
为了证实我们的主意,接着改写上面的例子:
let number = 1;
switch(number){
case 1:
let name = 'jony';
break;
case 2:
name = 'yu';
break;
}
我们把number改成1,我们发明代码不会报任何的毛病,由于此时let name的定义和赋值都被实行了。
三、范例和检测
一、什么时候会涌现题目
能够会说为何在本身的项目中,在ES6或许TS代码中纵然有上述的毛病运用,也没有报错?
笔者之前也有如许的题目,要明白的是是不是你把ES6或许TS的代码直接转化成了es5,然后再调试或许宣布的线上的,当let被编译成es5后,固然就不会存在上述switch中作用域的题目。然则实际中,编译成es5后的js文件能够太大,关于高版本浏览器我们愿望直接运用ES6代码(经由历程type = module来推断浏览器关于ES6的支撑性),那末这么上述题目就会涌现。
二、怎样检测和躲避
那末怎样防止这类状况呢,固然最好的体式格局,就是不要在case中定义块级变量,然则万一不小心写了上述的题目代码怎样检测呢。
起首运用typescript,静态编译是不能涌现毛病提醒的,由于这个毛病是运行时非常。最好的体式格局是经由历程编写eslint的范例来处理上述的不法运用题目。