44.运算符和运算符的优先级

位运算符

位运算符中比较常用的是:或运算与与运算。位运算符直接处理的是每一个比特位,是非常底层的运算,常常用在加密算法中,好处是速度比较快,缺点是不直观,增加了代码的复杂度,提升了维护成本。

或运算(or):符号为|,两个二进制位都为0,则结果为0,否则为1
与运算(and):符号为&,两二进制位都为1,结果为1,否则为0

console. log( 1 | 3); // 3,等同于:1表示为二进制是001,3表示为二进制是011,因此最后结果为011,转化为十进制即为3
console. 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指左值

运算符操作结合性类型
++自增Rlval->num
--自减Rlval->num
-求反Rnum->num
+(一个操作数)转换为数字Rnum->num
~按位求反Rint->int
!逻辑非Rbool->bool
delete删除属性Rlval->bool
typeof检测数据类型Rany->str
void返回undefinedRany->undefined

*、/、%乘、除、求余Lnum,num->num

+、-加、减Lnum,num->num
+字符串拼接Lstr,str->str
<、<=、>、>=数字大小或字母表顺序Lnum/str,num/str->bool
instanceof对象类型Lobj,function->bool
in测试属性是否存在Lstr,obj->bool

==判断相等Lany,any->bool
!=判断不等Lany,any->bool
===判断恒等Lany,any->bool
!==判断非恒等Lany,any->bool

&&逻辑与Lany,any->any
||逻辑或Lany,any->any
?:条件运算符Rbool,any,any->any
=赋值 *=、/=、+=、-=赋值 运算且赋值Rlval,any->any
,忽略第一个操作数,返回第二个操作数Lany,any->any

有几个我们需要注意的地方

  1. typeof的优先级相当的高,比加减乘除神马的都高,所以虽然是操作符,在在复杂表达式的时候我们还是习惯加括号,看个例子

     typeof 2*3;//NaN
     typeof (2*3);//"number"
     typeof 2+3;// "number3"
    
  2. ++--是右结合的操作符(优先级最高的几个都是右结合),而且比加减乘除优先级高。同时自增、自减运算符的运算数得是左值(可以放在赋值符号左边的值),而不能是常数

     4++; //ReferenceError: Invalid left-hand side expression in postfix operation
     var a=0,b=0;
     a+++b;//0
     a;//1,++优先级比+高,所以相当于(a++)+b
     b;//0
    
  3. 赋值运算符的优先级相当的低

     a = b == c; //等同于a = (b==c)
    
  4. 逻辑非!也在优先级队列的前端,比加减乘除高,但逻辑与、逻辑或优先级很低,不如加减乘除

     !2*0; //0, 等价于(!2)*0
    
  5. 一个关于逻辑运算符的有意思地方是其“短路”功能,相信大家都有所了解,但有些题目不那么单纯,会结合表达式计算值来考察

     1 && 3;
     1 && "foo" || 0;
     1 || "foo" && 0









作者:HungerLyndon
链接:https://www.jianshu.com/p/2fb26d610259
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值