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)。