位运算符
位运算符中比较常用的是:或运算与与运算。位运算符直接处理的是每一个比特位,是非常底层的运算,常常用在加密算法中,好处是速度比较快,缺点是不直观,增加了代码的复杂度,提升了维护成本。
或运算(or):符号为
|
,两个二进制位都为0,则结果为0,否则为1
与运算(and):符号为&
,两二进制位都为1,结果为1,否则为0console. log( 1 | 3); // 3,等同于:1表示为二进制是001,3表示为二进制是011,因此最后结果为011,转化为十进制即为3console. log( 1 & 3); // 1,等同于:1表示为二进制是001,3表示为二进制是011,因此最后结果为001,转化为十进制即为1布尔运算符
!
取反运算符&&
且运算符||
或运算符condition? true case : false case
三元条件运算符
算术运算符
算术运算符中最常见的是加法运算符,但是加法运算符针对不同类型的变量,组合效果有很多种。简而言之,JS中的加法运算符可以实现数字的相加,也可以实现字符串的拼接。
// ————数字相加———— console.log(1 + 1); // 2 console.log(true + true); // 2 console.log(1 + true); // 2 console.log(false - 1); // -1 // ————字符串拼接———— console.log('1'+'1'); // '11' console.log('1.1' + ' ' + '1.1'); // '1.1 1.1'
加法的计算方法一般如下:
1.1.1.1.如果运算元素是对象,那么会先转化为原始类型的值(即
valueOf
方法),如果其结果还不是原始类型的值,再调用toString
方法
var obj = {name: 'Lyndon', age: 22}; console.log('1' + obj); // '1[object Object]'
var obj = { name: 'Lyndon', toString: function toString(){ return 'Lyndon'; }, valueOf: function valueOf(){ return 'morning' } }; console.log(1 + obj); // '1morning' var obj = { name: 'Lyndon', toString: function toString(){ return 'Lyndon'; } }; console.log(1 + obj); // '1Lyndon'
2.2.2.2.如果对象是
Date
实例,那么先执行的是toString
方法
var day = new Date(); console.log(day); // 'Sat Dec 31 2016 19:19:11 GMT+0800 (中国标准时间)' console.log('good' + day); // 'goodSat Dec 31 2016 19:19:11 GMT+0800 (中国标准时间)'
3.3.3.3.两个运算元素都是原始类型值,但只要有一个运算元素是字符串,那么另一个运算元素也会转换为字符串,执行字符串拼接
var a = 10, b = 'days'; console.log(a + b); // '10days'
4.4.4.4.只有加号和一个运算元素,如果唯一的运算元素是字符串,那么会转换为数字,所以结果有可能是
NaN
console.log(+ '78'); // 78 console.log(+ 'good'); // 'NaN'
5.5.5.5.否则,两个运算元素皆转换为数值,执行算术加法运算
由于加法运算极大地依赖于参数的类型,因此使用时应该首先明确到底要执行哪种运算,如果不确定最好加上小括号。如下面的例子就说明字符串在算式中的位置不同,结果也会不同。
console.log('3' + 4 + 5); // '345' console.log(3 + 4 + '5'); // '75' console.log(3 + '4' + 5); // '345'
相较加法运算符而言,剩下的算术运算符都相对简单些,其原则就是:将所有的运算元素全部转换为数值,再执行相应的算术运算。
'1'/2; // 0.5 'a'/2; // NaN '1a'/2; // NaN,转换为数字的方式是Number('1a'),而不是parseInt('1a')
var a = 1, b = 1; a1 = a++; b1 = ++b; console.log(a1, b1, a, b); // 1 2 2 2
void运算符
void运算符的作用是:执行表达式,然后只返回
undefined
,由于void的优先级比较高,因此使用时最好加上小括号
console.log(void 1 + 2); // NaN,等同于:undefined + 2 console.log(void(1 + 2)); // undefined
逗号运算符
逗号运算符的作用是对两个表达式求值,然后返回后一个表达式的值。
1, 10; // 10 var x = 1; var y = 10; var z = (x, y); z; // 10
运算符优先级与结合性
优先级什么意思大家都清楚,结合性是指多个具有同样优先级的运算符表达式中的运算顺序。有的运算符是左结合的,即运算从左到右执行,下面两个运算是一样的
w = x + y + z; w = (x + y) + z;
有的运算符是右结合的
w = x = y = z; w = (x = (y = z)); w = a: b: c ? d : e? f : g; w = a? b : (c? d: (e? f : g));
运算符的优先级《JavaScript权威指南》中有个表阐述的很好(我去掉了位运算部分),其中R/L代表结合性是右结合还是左结合,num->num表示操作符期望的数据类型和计算结果类型,lval指左值
运算符 操作 结合性 类型 ++ 自增 R lval->num -- 自减 R lval->num - 求反 R num->num +(一个操作数) 转换为数字 R num->num ~ 按位求反 R int->int ! 逻辑非 R bool->bool delete 删除属性 R lval->bool typeof 检测数据类型 R any->str void 返回undefined R any->undefined *、/、% 乘、除、求余 L num,num->num +、- 加、减 L num,num->num + 字符串拼接 L str,str->str <、<=、>、>= 数字大小或字母表顺序 L num/str,num/str->bool instanceof 对象类型 L obj,function->bool in 测试属性是否存在 L str,obj->bool == 判断相等 L any,any->bool != 判断不等 L any,any->bool === 判断恒等 L any,any->bool !== 判断非恒等 L any,any->bool && 逻辑与 L any,any->any || 逻辑或 L any,any->any ?: 条件运算符 R bool,any,any->any =赋值 *=、/=、+=、-= 赋值 运算且赋值 R lval,any->any , 忽略第一个操作数,返回第二个操作数 L any,any->any
有几个我们需要注意的地方
typeof的优先级相当的高,比加减乘除神马的都高,所以虽然是操作符,在在复杂表达式的时候我们还是习惯加括号,看个例子
typeof 2*3;//NaN typeof (2*3);//"number" typeof 2+3;// "number3"
++
、--
是右结合的操作符(优先级最高的几个都是右结合),而且比加减乘除优先级高。同时自增、自减运算符的运算数得是左值(可以放在赋值符号左边的值),而不能是常数4++; //ReferenceError: Invalid left-hand side expression in postfix operation var a=0,b=0; a+++b;//0 a;//1,++优先级比+高,所以相当于(a++)+b b;//0
赋值运算符的优先级相当的低
a = b == c; //等同于a = (b==c)
逻辑非
!
也在优先级队列的前端,比加减乘除高,但逻辑与、逻辑或优先级很低,不如加减乘除!2*0; //0, 等价于(!2)*0
一个关于逻辑运算符的有意思地方是其“短路”功能,相信大家都有所了解,但有些题目不那么单纯,会结合表达式计算值来考察
1 && 3; 1 && "foo" || 0; 1 || "foo" && 0
作者:HungerLyndon
链接:https://www.jianshu.com/p/2fb26d610259
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。