javascript应该注意的小case--操作符

    

      javascript做为一个脚本语言,像它的前辈一样提供了操作数据值的操作符,如算术操作符、位操作符、关系操作符和相等操作符。你可以按照其它常用语言如C、C#等一样来使用js的操作符,但是远不如此,它的使用对象不仅限于特定类型,可以对任何类型使用,同时在处理时有着很大的不同。

 

算术操作符

      对数字类型执行++、—、+、-操作不用多说了,js可以对其它任何类型执行这个操作,让我们看几个实例:

先声明一些变量,这些变量是这篇文章中的例子都会用到的:

       var a = 123;
       var b = "123";
       var c = "123d";
       var e = true;
       var f = false;
       var g = {};

       function h_f() { };
       h_f.prototype.valueOf = function () { return 123; };
       h_f.prototype.toString = function () { return 456; };
       var h = new h_f();

       var i_f = function(){};
       i_f.prototype.toString = function () { return 123; };
       var i = new i_f();

 

然后执行如下操作:

       a++;b++;c++;e++;f++;g++;h++;i++;

       console.log(a + "|" + b + "|" + c + "|" + e + "|" + f + "|" + g + "|" + h + "|" + i);

 

      在浏览器的控制台,可以看到结果:124|124|NaN|2|1|NaN|124|124,这样我们可以得出一个简单的结论,js会自动为操作数调用Number()转换先将操作数转化为数值,然后再执行操作。Number()转换的规则,请见javascript应该注意的小case--数据类型

 

      其实js只是在执行这样的数值操作如++、—、一元+、一元和二元-、*等时,对操作数执行的Number()的转换操作,但是对于二元的相加操作+却不是:如果任何一个值为字符串,js会自动为另一个操作数执行toString()的操作,然后执行字符串拼接。

 

布尔操作符(!、&&、||)

     其实我们大部分见到它们时候是和逻辑判断语句一块的,如if(condition1 && !condition2 || condition3)这样的语句,在javascript应该注意的小case--数据类型中我们知道js为默认为这样的语句执行Boolean()的操作,但是我们现在主要讨论的是如下面例子的操作。

 

console.log(!a + "|" + !b + "|" + !c + "|" + !e + "|" + !f + "|" + !g + "|" + !h + "|" + !i);

 

     其中变量还是上个例子的,得到如下结果:false|false|false|false|true|false|false|false,如果这里我们还可以认为是对操作符执行Boolean()操作之后再执行正常的逻辑非的操作,而对于&&、||却完全不是这样了。(通常我们会连用两个非操作,如!!a来模拟Boolean()转换)

 

如下面的例子:

       console.log(e && a);

       console.log(f && a);

       console.log(b && a);

       console.log(undefined && a);

       console.log(null && a);

 

       我们得到的结果是123、false、123、undefined、null。有了这样的结果,我们似乎可以得出其中的规则:第一个操作数的Boolean()转换为true,就返回第二个操作数,如果为false,返回第一个操作数。其实&&操作是短路操作,只有第一个操作数转换为true时,才会去处理第二个操作数并返回结果;如果为false,直接返回第一个操作数。

 

      而 || 操作数与 && 相反,只有当第一个操作数转换的值为false时,才会处理第二个操作数,并返回第二个操作结果。

 

      事实上我们可以看到很多地方的应用,如var obj = otherObj || {};这样的操作就很好理解了,如果otherObj存在,obj就获得了引用;如果不存在,相当于一个新对象。总是能保证obj不为null.

 

关系操作符(>、>=、<、<=)

      有了以上的基础,对于js这样的操作,可能就有些心理准备,不会那么突兀了。

 

      规则如下:如果都是数字类型,直接比较;如果都是字符串,刚会比较对应位的字符编码值;如果有一个是数字类型,则把另一个转换为数值类型;如果是对象,先调用valueOf方法,如果没有些方法调用toString方法,再执行以上规则;如果有一个是布尔型 ,则将布尔型先转为数值类型再比较。

 

相等操作符(==、!=、===、!==)

还是先看例子:

       console.log(55 == "55");

 

你能猜测下结果吗?false??

再看下面的例子:

       console.log(55 == "55");

       console.log(55 === "55");

 

或许到这里,你已经能得猜测出答案了:true、false。

 

       先说全等操作===、!==,这个操作就是比较原始值,不对值进行任何的转换,这个是如此的确定,因些推荐大家使用全等的操作,避免一些诡异的bug。

 

       再来说==、!=,他们会对操作数执行强制转换,然后再比较:如果是操作数是布尔值,把true转为1、false转为0;如果一个是字符串,一个是数字,则将字符串转为数字再比较;如果一个是对象,另一个不是,则调用对象的valueOf之后,再按以上的规则比较。

 

       在进行以上的比较之前,有一些特殊会被执行:null与undefined相等比较返回true;null、undefined不会进行任何的类型转换;NaN不与任何值相等,甚至是自己;如果两个都是对象,只有两个操作数是同一个对象时才相等。

 

     本文并没有详细的介绍js所有的操作符,只是就js在操作符上与其它常用语言不一样的独特之处列举一二,了解了这些,至少不会让我们在读一些开源框架js代码时一头雾水,并且可以让我们的js代码更简洁、更安全(少出bug)。

posted @ 2012-04-21 17:36  for certain  阅读(1769)  评论(2编辑  收藏  举报