您的位置:首页 > Web前端 > JavaScript

第三章:基本概念(操作符)

2017-03-15 09:08 183 查看
操作符
递增和递减操作符

一元加和减操作符

位操作符
按位非

按位与

按位或

按位异或

左移

右移有符号右移无符号右移

布尔操作符

乘性操作符

加性操作符
加法

减法操作符

关系比较符

相等操作符
相等和不相等

全等和不全等

条件操作符

赋值操作符

逗号操作符

操作符

定义:操作符能用于操作数据值,包括算术运算符、位操作符、关系操作符和相等操作符。操作符能适用于很多值,例如字符串、数字值、布尔值,甚至对象。在应用于对象时,相应的操作符通常会调用对象的valueOf()和(或)toString()方法,以便取得可以操作的值。

递增和递减操作符

(+ +,- -)应用于数值时,和java中没有区别。要注意的是操作符的位置分为前置和后置。前置递增使变量的值在语句被求以前改变(可以理解成返回递增后的值)。举个例子:

var age = 29;
//以下几个都是单独存在:
var anotherage = ++age + 1;//31 age的值会在(++age) + 1之前改变(想象++age已经计算完毕),
所以最终得到了31。这种在科学领域称为副效应。
var anotherage = age++ + 1;//输出30 刚好与前置递增相反。
var anotherage = age++ + age + 1;//输出60 第一个age++返回了29,第二个age已经是30,再加1得到60
var anotherage = ++age + age + 1;//输出61
var anotherage = age + ++age + 1;//输出60 上面的现象与java中一模一样


当递增递减操作符应用于字符串、布尔值或者对象时。可以理解成在上一篇文章中提到过的,先将变量通过Number()函数转换为数值,再进行计算。这里就简单举3个object的例子:

var o1 = {
valueOf : function () {
return "1";
},
toString : function () {
return "2";
}
}
var o2 = {
toString : function () {
return "2";
}
}
var o3 = {
valueOf : function () {
return "1xx";
},
toString : function () {
return "2";
}
}
var o4 = {
valueOf : function () {
return "1xx";
},
toString : function () {
return "2xx";
}
}
alert(++o1);//2
alert(++o2);//3
alert(++o3);//NaN
alert(++o4);//NaN


o1和o2的结果是在预想中的,在执行自增运算时,先是求Number(o1),由于o1是对象,故先调用valueOf()方法再得到有效值”1”后,再执行Number(“1”)返回数值1自增得到2。o2的结果是因为没有重写valueOf方法,或者说valueOf方法的返回值执行Number后是NaN,所以再调用toString()最终得到3。o4的执行结果我也是可以理解的,两个都是NaN故最终结果是NaN。但是o3的结果就令我非常困惑了。书上的原话是执行valueOf得到NaN会再去调用toString。(后来我看到减法操作,发现如果有valueOf方法则使用valueOf方法的返回结果)那么按照我的理解o3最终是会得到3的。但是实验告诉我结果是NaN。我用的是Chrome浏览器,是不是书上说的已经过时了,还是我理解的不对。希望有人看到这个能评论讨论一下这个内容。这里再顺便说下如果在alert(++o4)之前alert(o4)是会输出2xx的,因为会自动调用在o4自增前o4还是个object,会自动调用toString()方法。而自增后o4已经变成一个Number类型了。

一元加和减操作符

注意这里说的是一元操作符,一元加操作符对于Number类型不会有任何变化(如果是减操作符就是取相反数)。如果是其他类型则执行Number()方法,以下是例子:

var s1 = "01";
var s2 = "1.1";
var s3 = "z";
var b = false;
var f = 1.1;
var o = {
valueOf: function() {
return -1;
}
};
//以下如果做一元减操作结果会取相反数。
s1 = +s1;   //value becomes numeric 1
s2 = +s2;   //value becomes numeric 1.1
s3 = +s3;   //value becomes NaN
b = +b;     //value becomes numeric 0
f = +f;     //no change, still 1.1
o = +o;     //va
4000
lue becomes numeric -1


位操作符

当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换为64位数值。这样表面看起来就好像是在操作32位数值。但这样会导致一个严重的副效应,再在特殊的NaN和Infinity值应用位操作时,这2个值会被当成0来对待。

按位非 (‘~’)

var num1 = 25;             //binary 00000000000000000000000000011001
var num2 = ~num1;          //binary 11111111111111111111111111100110
alert(num2);               //-26


按位非操作其实就相当于取反减一。但其速度会优于取反减一操作。

按位与 (‘&’)

按位与有2个操作数。与运算是在两个值都为1的时候才为1,这里省略例子。

按位或 (‘|’)

按位或有2个操作数。或运算是在两个值都为0的时候才为0,这里省略例子。

按位异或 (‘^’)

按位异或有2个操作数。异或运算是在两个值都不相同的时候才为1,这里省略例子。

左移(‘<<’)

左移运算就是把32位下的后31位(除去符号位)进行左移,右边多出来的空位填0。例子如下:

var a = 2;
alert(a << 2);//得到8相当于乘以2^n


右移(有符号右移’>>’,无符号右移’>>>’)

通常来说右移相当于除以2操作。有符号右移与左移类似。无符号右移对于正数来说和有符号右移没有区别。但是对负数进行无符号右移时,由于负数存的是补码,此时会将其当做正数处理,所以一般会造成得到的结果非常大。

布尔操作符

布尔操作符有3个(!, &&, ||),和java中用法相同。以下分别对三个操作符进行说明:

逻辑非(!):只有一个操作数,可以应用任何值,无论这个值是什么都会返回布尔值(注意和下面两个操作符的区别)。其实它的功能总结起来就是先用Boolean()函数对这个值取结果,然后再进行逻辑非运算。所以连续两个逻辑非’!!’的效果和Boolean()是一模一样的。

逻辑与(&&):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。

alert("12" && true);//true
alert("" && "34");//""
alert("12" && "34");//"34"
alert(true && "34");//"34"
alert(null && "34");//"null"
alert(NaN && null);//NaN
alert(undefined && null);//undefined
alert(false && null);//false


因为逻辑与操作符是短路操作符(逻辑或操作符也是),所以上述的结果其实很好理解了。首先会对第一个操作数进行Boolean()操作。如果是false,那么对不起直接返回第一个操作数的原型(原来是什么就返回什么),第二个到底是什么就不管了(即使第二个操作数未定义)。如果第一个是true。再去对第二个操作数进行Boolean()操作,如果还是true,那就返回第二个操作数的原型。那如果第二个操作数是false。那么也会返回第二个操作数的原型。所以总结下来就是( 以下是我的个人总结,如有不对欢迎指出。):

第一个操作数使用Boolean()计算是false,则返回第一个操作数原型。

第一个操作数使用Boolean()计算是true,则返回第二个操作数原型。

逻辑或(||):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。类比上面的逻辑与操作符有总结如下:

第一个操作数使用Boolean()计算是true,则返回第一个操作数原型。

第一个操作数使用Boolean()计算是false,则返回第二个操作数原型。

alert("12" || true);//"12"
alert("" || "34");//"34"
alert("12" || "34");//"12"
alert(true || "34");//true
alert(null || "34");//"34"
alert(NaN || null);//null
alert(undefined || null);//null
alert(false || null);//null


小tips:上述逻辑或的特性常用于给函数赋默认值,如下:

function getAjaxResponse(url,method) {
method = method || "get";
...
}
/*上述做法当调用getAjaxResponse("hello world!")时,
*由于method未传,在函数中为undefined,
*/利用逻辑或的特性可以为method赋值"get"


乘性操作符

乘性操作符包括乘除和取余。总结一句话就是如果操作数不是数值类型,利用Number()隐性转换。如果操作数中包含NaN,那么结果是NaN。如果包含Infinity:

Infinity * Infinity = Infinity

Infinity / Infinity = NaN

Infinity % Infinity = NaN

10 / Infinity = 0

10 / 0 = Infinity

0 / 0 = NaN

加性操作符

加法

普通数值操作就不说了,以下是几个特例

console.log(+0 + +0);//"0"
console.log(-0 + -0);//"-0" alert不会体现
/*
*如果操作数不是数字,当其中有一个为字符串时,
*转成字符串进行拼接。(前一章有提到)(书上说是toString,
*但实验结果说明valueOf优先于toString)。
*如果两者都不是字符串,则通过Number()获取两个结果进行加法运算。
*/
var a;
var b = "123";
var c = 123;
alert(a + b);//"undefined123"
alert(a + c);//NaN 这里认为是数值加法运算


var a = {
valueOf: function () {
return 1;
},
toString: function () {
return 2;
}
}
var b = {
valueOf: function () {
return 4;
},
toString: function () {
return 8;
}
}
var c = "hello";
alert(a);//输出2 前面章节提到过
alert(a + c);//输出 "1hello" 这里会先调用valueOf
alert(a && c);//输出 "hello" a不是空对象为true
alert(a || c);//输出 2 这里会先调用toString
alert(a + b);//输出5


减法操作符

减法同加法没有什么区别,唯一的区别是减法没有截取字符串一说。以下是例子:当遇到操作数不是数值的时候,会隐性的调用Number()方法转成数值。

var a = {
valueOf: function () {
return 1;
},
toString: function () {
return 2;
}
}
var b = {
toString: function () {
return 8;
}
}
var c = "hello";
var d = "1";
var e = "1xx";
alert(a - c);//输出 NaN (1-NaN) 这里会先调用valueOf
alert(a - b);//输出-7
alert(a - d);//输出0
alert(a - e);//输出NaN (1-NaN)


关系比较符(>, <, >=, <=)

如果两个操作数都是数值,执行数字比较。

如果都是字符串,比较对应的字符编码值。(按高到低)

如果一个是数值,则将另外一个操作数通过Number()转换为数值进行比较。

如果一个操作数是对象,调用valueOf方法。如果没有valueOf方法则调用toString()方法。再按照前三条规则比较。

如果是布尔值则通过Number()转换成数值,再按照前三条。

var a = "123";
var d = "123xx";
var b = {
valueOf: function () {
return 2;
},
toStrong: function () {
return "2";
}
}
var c = {
toStrong: function () {
return "2";
}
}
alert(a > b);//true 先是valueOf返回数值2 再将"123"转为数值123 比较得到true
alert(a > c);//false 先是toString返回字符串"2"  "123" < "2"
alert(d > 1 || d <= 1);//false 先是Number()返回NaN NaN不管怎么比较都是false


相等操作符

相等和不相等(==, !=)

如果一个操作数是布尔值,先转成数值再进行比较。

如果一个是字符串,一个是数值,则将字符串转成数值比较(可能得到NaN)。

如果一个是对象,一个不是,则调用该对象的valueOf方法(如果valueOf返回的还是对象则调用toString),通过返回的值的类型再按照上面规则进行比较。

null 和 undefined相等,且不能将其转换成其他值。

如果操作数中有NaN, 相等永远为false。不等永远为true。(NaN != NaN)

如果都是对象,则比较他们是不是同一个对象。如果指向同一个对象返回true。

全等和不全等(===, !==)

全等比较符除了在比较前不转换类型外,其他都与相等操作符一样。(null !== undefined)

条件操作符

和java中一样。例如:

var max = (num1 > num2) ? num1 : num2;


赋值操作符

此处简单略过,使用类似 += -=其实主要目的是简化赋值操作。不会带来性能的提升。有以下几个赋值操作:

*=

/=

%=

+=

-=

<<=

>>=

>>>=

逗号操作符

使用逗号操作符多用于声明多个变量。除此之外,逗号操作符还可以用于赋值。用于赋值时,逗号操作符总会返回表达式中的最后一项。例子如下:

var num1=1, num2=2, num3=3;
var num = (1, 2, 3, 4, 5);//num最终为5
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  javascript