【踩坑记事】关于我被switch语句折腾的3小时
0. 前言
记一次这周在项目上遇到的一个问题,为解决这个问题我和朋友研究了大概两三个小时。我们都是第一次遇到这种问题,请大佬勿喷,下面我来讲一下这个问题的成因和解决的办法。
直接说结果[问题结论](#4. 问题解决)
1. 问题来源
在目前这个项目中有一个函数需要根据后端返回返回的数据,分别进行不同操作。因为要执行不同的操作的判断有点多,所以决定使用switch
语句来进行判断。
一般来说switch
语句是长这样的:
1 | switch (expr) { |
我写的代码也是这样的格式,但是很奇怪的是在浏览器中运行会报一个非常奇怪的错误。
提示我“未捕获(在promise中)ReferenceError:在初始化之前无法访问orderID
”,就很奇怪哎,我这个orderID
已经是在全局声明了,并且如果实在switch
外面打印这个orderID
是可以正常访问的。然后我开始怀疑是不是switch
语句写错了?但是经过排查发现好像没有啥问题呀!然后我们就开始排错。
2. 问题排查
首先我们开始尝试在switch case
内部去let一个orderID
,发现还是会报上述错误。于是我们想到是不是是orderID
这个变量名的问题呢?然后我们就随便声明一个变量,用这个随便声明的变量去接函数的返回值,发现这个随便声明的变量是可以正常访问的。这就我们感觉非常奇怪的,为什么会出现这种情况呢?接着我们就在想会不会是switch
语句内部哪里出现了问题,然后我们开始挨个注释case
判断是哪一个case
出现了问题。然后最后发现case 1:
被注释掉了这个判断就正常了,那么这个case 1:
和其他的有什么不同呢?
看到这,我也是没有搞明白为什么会这样?直觉来讲,其他的case
也不会跑到case
里面来找变量吧,然后就网上找文档到底是怎么一回事。
3. 问题结论
最后在网站找到一篇文章说case语句的变量声明是在整个switch语句中可见的。
emmmm
这就很反直觉了。
这里引用部分原文
1、case语句的变量声明是在整个switch语句中可见的。
2、case语句中可以变量声明和定义,但在case语句中变量初始化的话有时会产生编译错误,原因是编译器为了避免“不一致”现象。具体解释如下:
- 因为case语句中的变量声明、定义、初始化实在整个switch语句中可见的,变量声明实在编译时完成,而变量初始化需要在执行是完成,所以,如果在一个非最后一个case的case(命名case1)中进行了变量声明加初始化(如int a=0;),若真正执行的时候switch的条件值是该case后面的某个case(命名case2)的值,则case2中可以看到a的声明,也可以使用啊,但是因为没有执行case1,所以a没有初始化,所以在case2中使用的a并不是“预想的”a,这就产生了不一致。但如果在case1中只有声明或定义,而没有初始化,则不会产生这种不一致,编译时就不会报错。
这个可以通过编译,因为此时在case ‘b ‘中a不可见(因为a在语句快中),所以不会出现上述的“不一致”现象,因此编译顺利通过。
此时也会顺利通过编译,因为a的定义(初始化)放在了最后一个分支中,由于在case ‘b ‘后面没有其他分支了,所以同样不会出现上述的“不一致”现象,所以仍然顺利通过编译。
4. 问题解决
这里提供一个解决问题的方法
- 不在
case
里面使用赋值解构 - 或者是使用
{}
包住要判断的内
例如:
1 | switch(val) { |