前端要给力之:代码可以有多烂?

前端要给力之:代码可以有多烂?

1、烂代码是怎么定义的?

!KissyUI是淘宝Kissy这个前端项目的一个群,龙藏同学在看完我在公司内网的“读烂代码系列”之后就在群里问呵:烂代码是怎么定义的?

是呵,到底什么才算烂代码呢?这让我想到一件事,是另一个网友在gtalk上问我的一个问题:他需要a,b,c三个条件全真时为假,全假时也为假,请问如何判断。

接下来KissyUI群里的同学给出了很多答案:

[javascript]view plaincopy
  1. //1.圆心
  2. if(a&&b&&c||!a&&!b&&!c){
  3. returnfalse
  4. }
  5. //2.龙藏
  6. (a^b)&c
  7. //3.愚公(我给gtalk上的提问者)的答案
  8. (axorb)or(axorc)
  9. //4.提问者自己的想法
  10. (a+b+c)%3
  11. //5.云谦对答案4的改进版本
  12. (!!a+!!b+!!c)%n
  13. //6.拔赤
  14. a?(b?c:b):(b?!b:!c)
  15. //7.吴英杰
  16. (a!=b||b!=c)
  17. (!a!=!b||!b!=!c)
  18. //8.姬光
  19. varv=a&&b&&c;
  20. if(!v){
  21. returnfalse;
  22. }elseif(v){
  23. returnfalse;
  24. }else{
  25. returntrue;
  26. }

en... 确实,我没有完全验证上面的全面答案的有效性。因为如同龙藏后来强调的:“貌似我们是要讨论什么是烂代码?”的确,我们怎么才能把代码写烂呢?上面出现了种种奇异代码,包括原来提问者的那个取巧的:

[Javascript]view plaincopy
  1. //4.提问者自己的想法
  2. (a+b+c)%3

因为这个问题出现在js里面,存在弱类型的问题,即a、b、c可能是整数,或字符串等等,因此(a+b+c)%3这个路子就行不通了,所以才有了

[javascript]view plaincopy
  1. //5.云谦对答案4的改进版本
  2. (!!a+!!b+!!c)%n

 

  2、问题的泛化与求解:普通级别

如果把上面的问题改变一下:

- 如果不是a、b、c三个条件,而是两个以上条件呢?

- 如果强调a、b、c本身不一定是布尔值呢?

那么这个问题的基本抽象就是:

[c-sharp]view plaincopy
  1. //v0,对任意多个运算元求xor
  2. functione_xor(){...}
  3. 对于这个e_xor()来说,最直接的代码写法是:
  4. //v1,扫描所有参数,发现不同的即返回true,全部相同则返回false。
  5. functione_xor(){
  6. varargs=arguments,argn=args.length;
  7. args[0]=!args[0];
  8. for(vari=1;i<argn;i++){
  9. if(args[0]!=!args[i])returntrue;
  10. }
  11. returnfalse;
  12. }

接下来,我们考虑一个问题,既然arguments就是一个数组,那么可否使用数组方式呢?事实上,据说在某些js环境中,直接存取arguments[x]的效率是较差的。因此,上面的v1版本可以有一个改版:

[javascript]view plaincopy
  1. //v1.1,对v1的改版
  2. functione_xor(){
  3. varargs=[].slice.call(arguments,0),argn=args.length;
  4. ...
  5. }

这段小小的代码涉及到splice/slice的使用问题。因为操作的是arguments,因此splice可能导致函数入口的“奇异”变化,在不同的引擎中的表现效果并不一致,而slice则又可能导致多出一倍的数据复制。在这里仍然选用slice()的原因是:这里毕竟只是函数参数,不会是“极大量的”数组,因此无需过度考虑存储问题。

3、问题的泛化与求解:专业级别

接下来,我们既然在args中得到的是一个数组,那么再用for循环就实在不那么摩登了。正确的、流行风格的、不被前端鄙视做法是:

[javascript]view plaincopy
  1. //v2,使用js1.6+的数组方法的实现
  2. functione_xor(a){
  3. return([].slice.call(arguments,1)).some(function(b){if(!b!=!a)returntrue});
  4. }

为了向一些不太了解js1.6+新特性的同学解释v2这个版本,下面的代码分解了上述这个实现:

[javascript]view plaincopy
  1. //v2.1,对v2的详细分解
  2. functione_xor(a){