运算符语法概述

在 JS 中,的运算符大多由标点符号表示,少数由关键字表示,它们的语法言简意赅,它们的数量却着实不少。

运算符始终都遵循着一些固定语法,只有了解并掌握这些内容,才能正确使用运算符。


操作数个数

JS 的运算符总共有 46 个,如果根据其操作数的个数进行分类,则大多数是二元运算符。

  • 所谓二元运算符,就是它们的操作数都是两个,它们将两个表达式合并成复杂表达式
1 + 2;
true || false;
  • 一元运算符:将一个表达式转换为另一个稍复杂的表达式,主要包括以下9个:
++ -- - + ~ ! delete typeof void
如,a++; typeof true;
  • 三元运算符只有一个,即:条件运算符,它将三个表达式合并成一个表达式。
2>1 ? 2 : 1;

优先级

运算符优先级控制着运算符的执行顺序,优先级高的运算符的执行总是先于优先级运算符低的运算符。

// JS中运算符的优先级总共分为14级,从高到低依次是:

   0 ()
   1  ++ -- - + ~ ! delete typeof void
   2  * / % + -
   3  << >> >>>
   4  < <= > >= instanceof in
   5  == != === !==
   6  &
   7  ^
   8  |
   9 &&
   10 ||
   11 ?:
   12 = *= /= %= += -= &= ^= |= <<= >>= >>>=
   13 ,

总结:一元运算符 > 算术运算符 > 比较运算符 > 逻辑运算符 > 三元运算符 > 赋值运算符 > 逗号运算符
// 注意:逻辑取反运算符属于一元运算符,其优先级最高

// 代码示例:

!2<1&&4*3+1;           // 像这种情况就比较复杂,逐步来分解其运算顺序

1. 先计算一元运算符!,!2; // false
   false < 1 && 4*3 + 1;
2. 计算算术运算符4*3+1;  // 13
   false < 1 && 13;
3. 计算比较运算符<,false<1;  // true
   true && 13;   // 13

推荐:可以使用圆括号来强行指定运算次序。

2+3*5;   // 17
(2+3)*5;   // 25;

结合性

结合性指定了在多个具有同样优先级的运算符表达式中的运算顺序。

多数运算符都具有从左向右的结合性,只有一元运算符、条件运算符和赋值运算符具有从右向左的结合性。

w = x + y + z;   // 等价于: w = ((x + y)+ z);

w = x = y = z; // 等价于: w = (x = (y = z));

q = a ? b : c ? d : e ? f : g; // 等价于: q = a ? b : (c ? d : (e ? f : g));

运算符的优先级和结合性决定了它们在复杂表达式中的运算顺序,但子表达式相互有影响时,顺序会发生变化。

a = 1;
b = a++ + a-- * a++;

// 分析:根据优先级的顺序,分别运算递增运算符、乘法运算符、加法运算符和赋值运算符
   1. 先计算第一个a++;   // 结果为1,a为2
      b = 1 + a-- * a++;
   2. 计算a--;   // 结果为2,a为1
      b = 1 + 2 * a++;
   3. 算第二个a++;   // 结果为1,a为2
      b = 1 + 2 * 1;
   4. 所以,最终a = 2; b = 3;        
      console.log(a,b);     // 2 3

类型

一些运算符可以作用于任何数据类型,但仍希望它们的操作数是指定类型的数据,并且大多数运算符返回一个特定类型的值。

在下面的运算符规则表中,箭头前为运算符操作数的类型,箭头后为运算结果的类型

[ 左值 ] 左值( lvalue )是一个古老的术语,指表达式只能出现在运算符的左侧。

  • 在 JS 中,变量、对象属性和数组元素都是左值
  • 递增运算符++、递减运算符--和赋值运算符的操作数类型是左值
var a = 3;
a++;   // 3
3--;   // 报错
({}).a += '1';   // 'undefined1'
'test' -= 'test';   // 报错

运算符规则表

运算符             操作                 类型
++                增量                 lval->num
--                减量                 lval->num
-                 求反                 num->num
+                 转换为数字            num->num
~                 按位求反              int->int
!                 逻辑非                bool->bool
delete            删除属性              lval->bool
typeof            检测类型              any->str
void              返回undefined         any->undef
******************************************************
* \ %             乘、除、求余           num,num->num
******************************************************
+ -               加、减                num,num->num
+                 字符串连接             str,str->str
******************************************************
<<                左移位                int,int->int
>>                有符号右移位           int,int->int
>>>               无符号右移位           int,int->int
******************************************************
< <= > >=         比较数字顺序           num,num->bool
< <= > >=         比较字母表顺序         str,str->bool
instanceof        测试对象类            obj,func->bool
in                测试属性              str,obj->bool
******************************************************
==                判断相等              any,any->bool
!=                判断不等              any,any->bool
===               判断恒等              any,any->bool
!==               判断非恒等            any,any->bool
******************************************************
&                 按位与                int,int->int
******************************************************
^                 按位异或              int,int->int
******************************************************
|                 按位或                int,int->int
******************************************************
&&                逻辑与                any,any->any
******************************************************
||                逻辑或                any,any->any
******************************************************
?:                条件运算符             bool,any,any->any
******************************************************
=                  赋值                 lval,any->any
*= /= %=
+= -= &=          运算且赋值             lval,any->any
^= |= <<=
>>= >>>=
******************************************************
,                 忽略第一个操作数,       any,any->any
                  返回第二个操作数