你是不是还在随意使用while循环?该小心一点了。

1,178 阅读4分钟

今天咱们来聊一个有意思的。不知道大家有没有发现。在我们日常的开发中。经常可以看见for循环,也有很多通过for循环衍生出来的内置方法。比如(for...in/for...of)之类的。 while身为for的兄弟,日常中几乎没有他的镜头。

先抛开while和for的性能不谈,其实这两个循环的性能对于浏览器的不同也会出现浮动。彼此之间的性能差距无限接近于0。不能带来什么什么问题。

while和for的使用场景

官方定义:↓

for:应用于已知遍历次数的情况下。

while:应用于遍历未知次数的情况下。

乍一听,是没啥问题的。for和while各司其职。

但,在日常的开发中,我们所遍历的数据,绝大多数情况下都是已知遍历次数的情况。 比如遍历一个对象,便利一个数组。便利的长度都是可以通过 .length 等方法获取的,都是已知长度,而while做为未知长度的循环方案。很少存在应用场景。这是while不会出现在大家眼中的原因之一。

其次:我们会刻意避开while的应用场景。

为什么避开while的应用场景。

注意:因为未知遍历次数是一件非常非常危险的事情。如果使用不恰当,非常容易造成项目的崩溃卡死。

比如呢:因为便利的次数无法确定,我们也无法保证是否会进入一个死循环或者暂时性死循环。

比如,你要去读取一个数据,但是我们不知道什么时候可以读取到数据,所以我们写了一个while循环一直去读。读到就break。结果某一天出现了一个意外情况,数据一直都读不到。while一直执行,然后就造成了线程阻塞,项目卡死,电脑cpu和内存被全部占满等一系列让人头皮发麻的情况。

image.png

所以,当我们遇到不知道遍历次数的时候。为了防止程序可能会陷入的死循环或者长时间的执行。我们会想办放让他变成可知的。所以,while的应用场景随之就少了,我们自然也就很少看见了。

作者踩过的坑

前几周,在一个物联网项目上。需要和设备进行通讯。但是因为设备的原因,我们无法保证一次指令就能读取到设备信息。需要多次发送指令。基于这个条件下。和我对接的A同事,就在读取设备信息的串口上写了如下逻辑(精简版)

while(true){
       const res = 读取设备信息的指令;
       if (res.code === 0){
         ...存储操作
         ...其他操作
          break;
     }
    }

大家发现什么问题了吗。

是的,如果设备是坏的,或者出现其它任何一个可以导致设备信息读取不上来的情况。基于while是同步运行的条件。程序就会陷入一个死循环。

image.png

以至于我合并完A同事的代码后,整个项目启动会出现偶发性死机,并且没有报错。 作为开发的各位,一定了解没有报错还偶尔的bug有多恶心。

image.png

所以后来,我将上述代码修改成了如下(精简版)

    for(let i =0;i<100;++i){
     const res =  读取设备信息的指令;
     if(res.code === 0){
         ...存储操作
         ...其他操作
          break;
     }
    }

读取100次,读不到那就读不到,读不到就让对方去首页刷新。总之绝不能让while一直去读。

while也可以实现循环指定长度,为什么大家都用for.

for版

  for(let i =0;i<100;++i){
     const res =  读取设备信息的指令;
     if(res.code === 0){
         ...存储操作
         ...其他操作
          break;
     }
    }

等同于

while版

let i=0;
while(i<100){
    ++i;
    const res =  读取设备信息的指令;
     if(res.code === 0){
         ...存储操作
         ...其他操作
          break;
     }
}

为什么我选用for而不是while?

为了减少全局变量/类全局变量的污染。尽量实现变量私有化。这和闭包的思想差不多。

使用while的话,我还需要在while以外的地方再定义一个变量。for则自己内部集成。无需额外定义。

仅仅从我个人角度说,我会尽量去避免使用while。

while也绝不是一无是处的

while虽然使用场景不多,但在循环次数未知,并且我可以保证这个循环不会占用大量的内存和陷入死循环的时候。我会使用while。

因为,while在写法上比for稍微少那么一丢丢。

谢谢你那么有耐心的看完,祝你好运