JavaScript “与或”运算符的妙用

http://www.smalluv.com/javascript_and_or_operator_magical_usage.html

JavaScript 中运用“与或”运算符有时会简化很多代码,而且不失易读性,下面就来看看“与或”运算符的妙用的妙用。

有时我们用条件语句if else来写代码会很麻烦,例如:

 1 var value = 0; 
 2 if(cond == 5){ 
 3     value = 1; 
 4 } 
 5 else if(cond == 10){ 
 6     value = 2; 
 7 } 
 8 else if(cond == 12){ 
 9     value = 3; 
10 } 
11 else if(cond == 15){ 
12     value = 4; 
13 } 
14 else { 
15     value = 0; 
16 }

 

换成switch稍好点,但也比较臃肿:

 

var value = 0; 
switch(cond){ 
    case 5 : value = 1; 
break; 
    case 10 : value = 2; 
break; 
    case 12 : value = 3; 
break; 
    case 15 : value = 4; 
break; 
    default : value = 0; 
break;

 

那么就来看看用“与或”运算符来简化:

 

var value = (cond==5 && 1) || (cond==10 && 2) || (cond==12 && 3) || (cond==15 && 4) || 0;

 

还不够简化?没问题:

 

var value={'5':1,'10':2,'12':3,'15':4}[cond] || 0;

 

首先我们来梳理一下一个概念,在js逻辑运算中,0、”"、null、false、undefined、NaN都会判为false,其他都为true。这个一定要记住,不然应用||和&&就会出现问题。

这里顺便提下:经常有人问我,看到很多代码if(!!attr),为什么不直接写if(attr);

其实这是一种更严谨的写法,请测试 typeof 5和typeof !!5的区别。!!的作用是把一个其他类型的变量转成的bool类型。

 

下面主要讨论下逻辑运算符&&和||:

几乎所有语言中||和&&都遵循“短路”原理,如&&中第一个表达式为假就不会去处理第二个表达式,而||正好相反。

js也遵循上述原则。但是比较有意思的是它们返回的值。

 

var attr = true && 8 && "aaa";

 

那么运行的结果attr就不是简单的true或这false,而是”aaa”

再来看看||:

 

var attr = attr || "";

 

这个运算经常用来判断一个变量是否已定义,如果没有定义就给他一个初始值,这在给函数的参数定义一个默认值的时候比较有用。因为js不像php可以直接在型参数上定义func($attr=5)。再次提醒你记住上面的原则:如果实参需要是0、”"、null、false、undefined、NaN的时候也会当false来处理。

 

if(a>=8){ 
  alert("hello"); 
}

 

可以写成:

 

a >= 5 && alert("hello");

 

这样只需一行代码就搞定。但是需要注意的一点就是:js中||和&&的特性帮我们精简了代码的同时,也带来了代码可读性的降低。这就需要我们自己来权衡了。

 

一方面精简js代码,能实质性的减少网络流量,尤其是大量应用的js公用库。个人比较推荐的做法是:如果是相对复杂的应用,请适当地写一些注释。这个和正在表达式一样,能够精简代码,但是可读性会降低,对读代码的人要求会高些,最好的办法就是写注释。

 

我们可以不使用这些技巧,但是我们一定要能看懂,因为这些技巧已经广泛应用,尤其是像JQuery等js框里的代码,不理解这些你就很难看懂别人的代码。 像var Fly = Fly || {};这种是非常广泛应用的。

 

再来看一段jQuery中的代码:

var wrap =
// option or optgroup
!tags.indexOf("<opt") &&
[ 1, "<select multiple='multiple'>", "</select>" ] ||

!tags.indexOf("<leg") &&
[ 1, "<fieldset>", "</fieldset>" ] ||

tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
[ 1, "<table>", "</table>" ] ||

!tags.indexOf("<tr") &&
[ 2, "<table><tbody>", "</tbody></table>" ] ||

// <thead> matched above
(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||

!tags.indexOf("<col") &&
[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

// IE can't serialize <link> and <script> tags normally
!jQuery.support.htmlSerialize &&
[ 1, "div<div>", "</div>" ] ||

[ 0, "", "" ];

// Go to html and back, then peel off extra wrappers
div.innerHTML = wrap[1] + elem + wrap[2];

// Move to the right depth
while ( wrap[0]-- )
div = div.lastChild;

 

这段代码是用来处理 $(html) 时约束某些标签的,如<option>必须在<select></select>之内。 很巧妙的地方就是 !tags.indexOf(“<opt”) ,这样简单地就实现了startWith的功能,没有一点多余的代码,怎么样,很强大吧。

 

个人理解:

|| 是为了寻找人世间的 "善美",遇到就返回;或者直到表达式结束才依依不舍的返回最后一个 操作数(无论真假)

&& 是那纯洁的天使,看到人世间的堕落就无法忍耐, 直接返回第一个 假的操作数 或者 开心的返回最后一个 操作数(无论真假)

注意:二者都挺懒,直接返回的是表达式中的该原始操作数,而不是true和false。

如上面的JQuery代码中,会直接返回一个数组  

[ 1, "<select multiple='multiple'>", "</select>" ]
posted @ 2013-05-17 15:41  HolyGrail  阅读(590)  评论(0)    收藏  举报
设计良好的程序将用户的注意力视为有限的宝贵资源,只有在必要时才要求使用。 ——《Unix编程艺术》