9月阅读周·JavaScript权威指南:表达式和运算符,运算表达式篇
背景
去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。
没有计划的阅读,收效甚微。
新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。
这个“玩法”虽然常见且板正,但是有效,已经坚持阅读八个月。
已读完书籍:《架构简洁之道》、《深入浅出的Node.js》、《你不知道的JavaScript(上卷)》、《你不知道的JavaScript(中卷)》、《你不知道的JavaScript(下卷)》、《数据结构与算法JavaScript描述》、《WebKit技术内幕》、《前端架构:从入门到微前端》、《秒懂算法:用常识解读数据结构与算法》。
当前阅读周书籍:《JavaScript权威指南》。
算术表达式
运算符“/”用第二个操作数来除第一个操作数,如果你使用过那些区分整型和浮点型数字的编程语言,那么当用一个整数除以另一个整数时,则希望得到的结果也是整数。但在JavaScript中,所有的数字都是浮点型的,除法运算的结果也是浮点型,比如,5/2的结果是2.5,而不是2。除数为0的运算结果为正无穷大或负无穷大,而0/0的结果是NaN,所有这些运算均不会报错。
运算符“%”计算的是第一个操作数对第二个操作数的模[插图]。换句话说,就是第一个操作数除以第二个操作数的余数。结果的符号和第一个操作数(被除数)的符号保持一致。例如,5%2结果是1,-5%2的结果是-1。
求余运算符的操作数通常都是整数,但也适用于浮点数,比如,6.5%2.1结果是0.2。
“+”运算符
二元加法运算符“+”可以对两个数字做加法,也可以做字符串连接操作:
1+2//=>3
"hello"+""+"there"//=>"hello there"
"1"+"2"//=>"12"
当两个操作数都是数字或都是字符串的时候,计算结果是显而易见的。然而对于其他情况来说,则要进行一些必要的类型转换,并且运算符的行为依赖于类型转换的结果。加号的转换规则优先考虑字符串连接,如果其中一个操作数是字符串或者转换为字符串的对象,另外一个操作数将会转换为字符串,加法将进行字符串的连接操作。如果两个操作数都不是类字符串(string-like)的,那么都将进行算术加法运算。
从技术上讲,加法操作符的行为表现为:
- 如果其中一个操作数是对象,则对象会遵循对象到原始值的转换规则转换为原始类值:日期对象通过toString()方法执行转换,其他对象则通过valueOf()方法执行转换(如果valueOf()方法返回一个原始值的话)。由于多数对象都不具备可用的valueOf()方法,因此它们会通过toString()方法来执行转换。
- 在进行了对象到原始值的转换后,如果其中一个操作数是字符串的话,另一个操作数也会转换为字符串,然后进行字符串连接。
- 否则,两个操作数都将转换为数字(或者NaN),然后进行加法操作。
这里有一些例子:
1+2//=>3:加法
"1"+"2"//=>"12":字符串连接
"1"+2//=>"12":数字转换为字符串后进行字符串连接
1+{}//=>"1[object Object]":对象转换为字符串后进行字符串连接
true+true//=>2:布尔值转换为数字后做加法
2+null//=>2:null转换为0后做加法
2+undefined//=>NaN:undefined转换为NaN后做加法
最后,需要特别注意的是,当加号运算符和字符串和数字一起使用时,需要考虑加法的结合性的对运算顺序的影响。也就是说,运算结果是依赖于运算符的运算顺序的,比如:
1+2+"blind mice";//=>"3 blind mice"
1+(2+"blind mice");//=>"12 blind mice"
第一行没有圆括号,“+”运算符具有从左至右的结合性,因此两个数字首先进行加法计算,计算结果和字符串进行连接。在第二行中,圆括号改变了运算顺序:数字2和字符串连接,生成一个新字符串,然后数字1和这个新字符串再次连接,生成了最终结果。
一元算术运算符
一元运算符作用于一个单独的操作数,并产生一个新值。在JavaScript中,一元运算符具有很高的优先级,而且都是右结合(right-associative)。本节将讲述一元算术运算符(+、-、++和--),必要时,它们会将操作数转换为数字。需要注意的是,“+”和“-”是一元运算符,也是二元运算符。、
下面介绍一元算术运算符:
一元加法(+)
一元加法运算符把操作数转换为数字(或者NaN),并返回这个转换后的数字。如果操作数本身就是数字,则直接返回这个数字。
一元减法(-)
当“-”用做一元运算符时,它会根据需要把操作数转换为数字,然后改变运算结果的符号。
递增(++)
递增“++”运算符对其操作数进行增量(加一)操作,操作数是一个左值(lvalue)(变量、数组元素或对象属性)。运算符将操作数转换为数字,然后给数字加1,并将加1后的数值重新赋值给变量、数组元素或者对象属性。
递增“++”运算符的返回值依赖于它相对于操作数的位置。当运算符在操作数之前,称为“前增量”(pre-increment)运算符,它对操作数进行增量计算,并返回计算后的值。当运算符在操作数之后,称为“后增量”(post-increment)运算符,它对操作数进行增量计算,但返回未做增量计算的(unincremented)值。思考一下如下两行代码之间的区别:
var i=1,j=++i;//i和j的值都是2
var i=1,j=i++;//i是2,j是1
需要注意的是,表达式++x并不总和x=x+1完全一样,“++”运算符从不进行字符串连接操作,它总是会将操作数转换为数字并增1。如果x是字符串“1”,++x的结果就是数字2,而x+1是字符串“11”。
同样需要注意的是,由于JavaScript会自动进行分号补全,因此不能在后增量运算符和操作数之间插入换行符。如果插入了换行符,JavaScript将会把操作数当做一条单独的语句,并在其之前补上一个分号。
不管是前增量还是后增量,这个运算符通常用在for循环中,用于控制循环内的计数器。
递减(--)
递减“-”运算符的操作数也是一个左值。它把操作数转换为数字,然后减1,并将计算后的值重新赋值给操作数。和“++”运算符一样,递减“--”运算符的返回值依赖于它相对操作数的位置,当递减运算符在操作数之前,操作数减1并返回减1之后的值。当递减运算符在操作数之后,操作数减1并返回减1之前的值。当递减运算符在操作符的右侧时,运算符和操作数之间不能有换行符。
位运算符
位运算符可以对由数字表示的二进制数据进行更低层级的按位运算。尽管它们并不是传统的数学运算,但这里也将其归类为算术运算符,因为它们作用于数值类型的操作数并返回数字。这些运算符在JavaScript编程中并不常用,如果你对十进制整数的二进制表示并不熟悉的话,你可以跳过本节内容。这里的4个运算符都是对操作数的每个位进行布尔运算,这里将操作数的每个位当做布尔值(1=true,0=false),其他三个位运算符用来进行左移位和右移位。
位运算符要求它的操作数是整数,这些整数表示为32位整型而不是64位浮点型。必要时,位运算符首先将操作数转换为数字,并将数字强制表示为32位整型,这会忽略原格式中的小数部分和任何超过32位的二进制位。移位运算符要求右操作数在0~31之间。在将其操作数转换为无符号32位整数后,它们将舍弃第5位之后的二进制位,以便生成一个位数正确的数字。需要注意的是,位运算符会将NaN、Infinity和-Infinity都转换为0。
按位与(&)
位运算符“&”对它的整型操作数逐位执行布尔与(AND)操作。只有两个操作数中相对应的位都是1,结果中的这一位才是1。例如,0x1234&0x00FF=0x0034。
按位或(|)
位运算符“|”对它的整型操作数逐位执行布尔或(OR)操作。如果其中一个操作数相应的位为1,或者两个操作数相应位都是1,那么结果中的这一位就为1。例如:0x1234|0x00FF=0x12FF。
按位异或(^)
位运算符“|”对它的整型操作数逐位执行布尔异或(XOR)操作。异或是指第一个操作数为true或第二个操作数为true,但两者不能同时为true。如果两个操作数中只有一个相应位为1(不能同时为1),那么结果中的这一位就是1。例如,0xFF00^0xF0F0=0x0FF0。
按位非(~)
运算符“~”是一元运算符,位于一个整型参数之前,它将操作数的所有位取反。根据JavaScript中带符号的整数的表示方法,对一个值使用“~”运算符相当于改变它的符号并减1。例如,~0x0F=0xFFFFFFF0或-16。
左移(<<)
将第一个操作数的所有二进制位进行左移操作,移动的位数由第二个操作数指定,移动的位数是0~31之间的一个整数。例如,在表达式a<<1中,a的第一位变成了第二位,a的第二位变成了它的第三位,以此类推。新的第一位用0来补充,舍弃第32位。将一个值左移1位相当于它乘以2,左移两位相当于乘以4,以此类推。例如,7<<2=28。
带符号右移(>>)
运算符“>>”将第一个操作数的所有位进行右移操作,移动的位数由第二个操作数指定,移动的位数是0~31之间的一个整数。右边溢出的位将忽略。填补在左边的位由原操作数的符号决定,以便保持结果的符号与原操作数一致。如果第一个操作数是正数,移位后用0填补最高位;如果第一个操作数是负的,移位后就用1填补高位。将一个值右移1位,相当于用它除以2(忽略余数),右移两位,相当于它除以4,以此类推,例如,7>>1=3,-7>>1=-4。
无符号右移(>>>)
运算符“>>>”和运算符“>>”一样,只是左边的高位总是填补0,与原来的操作数符号无关,例如,-1>>4=-1,但是-1>>>4=0x0FFFFFFF。
总结
基本的算术运算符是*(乘法)、/(除法)、%(求余)、+(加法)和-(减法)。剩下的4个运算符非常简单,只是在必要的时候将操作数转换为数字而已,然后求积、商、余数和差。所有那些无法转换为数字的操作数都转换为NaN值。如果操作数(或者转换结果)是NaN值,算术运算的结果也是NaN。
作者介绍
非职业「传道授业解惑」的开发者叶一一。
《趣学前端》、《CSS畅想》等系列作者。华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。
如果看完文章有所收获,欢迎点赞👍 | 收藏⭐️ | 留言📝。
- 点赞
- 收藏
- 关注作者
评论(0)