js的一元运算符+运算顺序、优先性与结合性
一元运算符只有一个参数,即要操作的对象或值。它们是 ECMAScript 中最简单的运算符。(有9个)
1,罗列:
1)delete:delete 运算符删除对以前定义的对象属性或方法的引用(结果是undefined,必须定义过,未定义或者继承来的都会报错)
使用:delete o.name;
2)void:void 运算符对任何值返回 undefined。该运算符通常用于避免输出不应该输出的值。
使用:void(num);
3)前增量/前减量运算符:前增量运算符,就是数值上加1,反之减1,增量和减量运算符都发生在计算表达式之前。
使用:++i; --i;
4)后增量/后减量运算符:与前相同,区别在于,增量和减量运算符都发生在计算表达式之后。
使用:i++; i--;
5)一元加/一元减:稍显复杂,见下文:
对数字进行一元加操作,结果返回数字本身,要注意对负数进行一元加操作结果还是负数啦,不要以为会得到整数; 对布尔类型进行一元加操作,true的话返回1,false返回0; 对null进行一元加操作,返0; 对undefined进行一元加操作,返回NaN; 对字符串进行一元加操作,有两种结果,如果字符串由纯数字构成的话,返回1,如果不是则返回NaN; 计算字符串的方式与 parseInt() 相似,只有对以 "0x" 开头的字符串(表示十六进制数字),一元运算符才能把它转换成十进制的值。因此,用一元加法转换 "010",得到的总是 10,而 "0xB" 将被转换成 11。 对对象进行一元加操作,也有两种结果,一是返回数字,二是返回NaN;操作过程中首先会调用valueOf方法,如果得不到数字结果,就调用toString方法,再对得到的字符串进行一元加操作;
一元减与一元加类似:区别所在见下文:
对数字使用:返回数字的负数;
对其他数据类型使用:首先尝试把表达式转换成数字,再取负数;
6)逻辑非:
2,运算顺序、优先性和结合性
1)首先是运算顺序和优先性,这个很简单,就是当出现表达式嵌套且所有的运算符不都是同一级时会出现运算顺序的差别,不是真正的运算顺序,而是优先级决定的先算谁的问题
实质上与小学时候的先乘除后加减相同,而对于多个表达式来说,整体的运算顺序永远是是从左像右的,但由于优先级的不同可能会出现细节上的不同,可以参考小学学过的四则运算;
举个栗子:
var a = 1; b = a ++ + ++ a; // 4 // 解析: // 先算a++,得到1,这时a的值变成了2; // 再算++a,得到3; // 1+3得到4; // 把4赋值给b;
运算顺序是从右向左,但是由于优先级不同,优先计算的表达式是a++和++a
所有运算符的优先级:参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence
其中有几个特例:
一元运算符、赋值运算符、三目运算符
我们试着来理解一下,只存在多个一元运算符时受体只能是同一个变量,此时不存在优先性的问题,那么此时计算顺序是什么呢?
此时引出了另一个概念:结合性
2)结合性:
首先要明确一点,结合性一定是在表达式中只存在同级运算符的情况下才会出现的一个概念:
分为两种,左结合与右结合,表示的是同级运算符存在时的运算顺序
其中,所有一元操作符、三目运算符和赋值运算符都是右结合,其他的操作符都是左结合
举个栗子:
!a++; // 如果是从左往右运算,!a先得到一个布尔类型,(!a)++最后得到一个数字类型; // 如果是从右往左运算,a++先得到一个数字类型,!(a++)后得到一个布尔类型; // 逻辑非(!)和递增操作符(++)都是一元运算符,当两个一元运算符同时存在于一行代码中时,从右往左运算,所以最后会得到一个布尔类型的结果; x = a ? b : c ? d : e ? f : g; // 三目运算符也是右结合的,从右向左运算,相当于 x = a ? b : (c ? d : (e ? f : g)); var a = b = c = d; // 连等赋值,也是从右向左运算,先取d的值,把它赋给c,再把c的值赋给b,再把b的值赋给a;
以上
综合起来说,当三种规则相遇时,优先级权重最大,当同一优先级时考虑结合性,然后再考虑运算顺序。