JavaScript 常见运算符
维基百科 --- 运算符
编程语言通常支持一组运算符:构造,其行为通常类似于函数,但在语法 或语义上 与通常的函数不同。常见的简单示例包括算术(加法
+),比较(加>)和逻辑运算(如AND或&&)。更多涉及的示例包括赋值 (通常=或:=),记录或对象(通常)中的字段 访问.,以及范围解析运算符 (通常::)。语言通常定义一组内置运算符,在某些情况下允许用户定义的运算符。
运算符的优先级
简单记忆法(需要具体问题具体分析):单目 > 算术 > 位移 > 关系 > 逻辑 > 三目 > 赋值
下面的表将所有运算符按照优先级的不同从高到低排列。
MDN运算符优先级
| 优先级 | 运算类型 | 关联性 | 运算符 |
|---|---|---|---|
| 20 | 圆括号 | n/a | (expr) |
| 19 | 成员访问 | 从左到右 | object.property |
需计算的成员访问 | 从左到右 | object[property] | |
new (带参数列表) | n/a | new Object(params) | |
| 函数调用 | 从左到右 | Function(params) | |
| 可选链(Optional chaining) | 从左到右 | a?.b | |
| 18 | new (无参数列表) | 从右到左 | new Object() |
| 17 | 后置递增(运算符在后) | n/a | expr++ |
| 后置递减(运算符在后) | n/a | expr-— | |
| 16 | 逻辑非 | 从右到左 | !expr |
| 按位非 | ~expr | ||
| 一元加法 | +expr | ||
| 一元减法 | -expr | ||
| 前置递增 | ++expr | ||
| 前置递减 | —expr | ||
typeof | typeof expr | ||
void | void expr | ||
delete | delete expr | ||
await | await expr | ||
| 15 | 幂 | expr**expr | |
| 14 | 乘法 | 从左到右 | expr * expr |
| 除法 | expr / expr | ||
| 取模 | expr % expr | ||
| 13 | 加法 | 从左到右 | expr + expr |
| 减法 | expr - expr | ||
| 12 | 按位左移 | 从左到右 | expr << expr |
| 按位右移 | expr >> expr | ||
| 无符号右移 | expr >>> expr | ||
| 11 | 小于 | 从左到右 | expr < expr |
| 小于等于 | expr <= expr | ||
| 大于 | expr > expr | ||
| 大于等于 | expr >= expr | ||
| in | expr in expr | ||
| instanceof | expr instanceof expr | ||
| 10 | 等号 | 从左到右 | expr = expr |
| 非等号 | expr != expr | ||
| 全等号 | expr === expr | ||
| 全等号 | expr !== expr | ||
| 9 | 按位与 | 从左到右 | expr & expr |
| 8 | 按位异或 | 从左到右 | expr ^ expr |
| 7 | 按位或 | 从左到右 | expr \| expr |
| 6 | 逻辑与 | 从左到右 | expr && expr |
| 5 | 逻辑或 | 从左到右 | expr \|\| expr |
| 4 | 条件运算符 | 从右到左 | expr ? expr : expr |
| 3 | 赋值 | 从右到左 | expr = expr |
expr += expr | |||
expr -= expr | |||
expr *= expr | |||
expr /= expr | |||
expr %= expr | |||
expr <<= expr | |||
expr >>= expr | |||
expr >>>= expr | |||
expr &= expr | |||
expr \|= expr | |||
expr ^= expr | |||
| 2 | yield | 从右到左 | yield expr |
| yield* | 从右到左 | yield* expr | |
| 1 | 展开运算符 | n/a | ...expr |
| 0 | 逗号 | 从左到右 | expr, expr |
1. 单目运算符
一元(单目)运算符只需要一个操作变量。
+: 一元加运算符将操作转换为Number类型.
-: 一元减运算符将操作转换为Number类型并取反.
!: 逻辑非运算符.
~: 按位非运算符.
delete: 运算符用来删除对象的属性.
void: 运算符表示表达式放弃返回值.
typeof: 运算符用来判断给定对象的类型.
var obj = { a: 123 };
function test() {}
console.log('before delete:', obj);
typeof obj;
delete obj.a;
console.log('typeof', typeof obj);
console.log('typeof', typeof test);
console.log('typeof', typeof '123');
console.log('typeof', typeof 321);
console.log('typeof', typeof undefined);
console.log('typeof', typeof null);
console.log('after delete:', obj);
console.log('void 0:', void 0);
console.log("+'1':", +'1');
console.log('+ object:', +obj);
console.log('+ function:', +test());
console.log('+ undefied:', +undefined);
console.log('+ null:', +null);
console.log('-1:', -1);
console.log("-'1':", -'1');
console.log('- object:', -obj);
console.log('- function:', -test());
console.log('- undefied:', -undefined);
console.log('- null:', -null);
console.log('!1:', !1);
console.log('!0:', !0);
console.log("!'1':", !'1');
console.log('~1:', ~1);
console.log("~'1':", ~'1');

2. 自增 & 自减运算符
++a: 先赋值后自增
a++: 先赋值后自增
—-a: 先自减后赋值
a-—: 先自减后赋值
var a = 0;
console.log('a++', a++);
console.log('a', a);
console.log('++a', ++a);
var b = 0;
console.log('b--', b--);
console.log('b', b);
console.log('--b', --b);

3. 算术运算符
2个数值(字面量或变量)作为操作数,并返回单个数值.
主要有+ - * / %.
4. 位移运算符
在二进制的基础上对数字进行移动操作
<<: 按位左移运算符. 左移 当前值的二进制 * 2 ^ (位数)
>>: 按位右移运算符. 左移 当前值的二进制 / 2 ^ (位数)
>>>: 按位无符号右移运算符.
有符号整数使用 31 位表示整数的数值,用第 32 位表示整数的符号,0 表示正数,1表示负数。数值范围从-2147483648到2147483647`。
二进制表示规则

正数左右位移


console.log('8 << 3', 8 << 3);
console.log('-1 << 3', -1 << 3);
console.log('8 >> 3', 8 >> 3);
console.log('-1 >> 3', -1 >> 3);
console.log('8 >>> 3', 8 >>> 3);
console.log('-1 >>> 3', -1 >>> 3);

5. 位运算符(Bitwise operators)
将其操作数(operands)当作32位的比特序列(由0和1组成),而不是十进制、十六进制或八进制数值。
&: 全1为1|: 见1为1^: 同为1, 异为0~:1变0,0变1
The production UnaryExpression :
**~**UnaryExpression* is evaluated as follows:
- Let expr be the result of evaluating UnaryExpression.
- Let oldValue be ToInt32(GetValue(expr)).
- Return the result of applying bitwise complement to oldValue. The result is a signed 32-bit integer.
中文:
产生式
UnaryExpression : ~ UnaryExpression按照下面的过程执行:
- 令
expr为解析执行UnaryExpression的结果- 令
oldValue为 ToInt32(GetValue(expr))- 返回
oldValue按位取反的结果
ToInt32过程:The abstract operation ToInt32 converts its argument to one of 232 integer values in the range −231 through 231−1, inclusive. This abstract operation functions as follows:
- Let number be the result of calling ToNumber on the input argument.
- If number is NaN, +0, −**0, +**∞, or −∞, return +0.
- Let posInt be sign(number) - floor(abs(number)).
- Let int32bit be posInt- modulo 232; that is, a finite integer value k of Number type with positive sign and less than 232 in magnitude such that the mathematical difference of posInt* and k is mathematically an integer multiple of 232.
- If int32bit is greater than or equal to 231, return int32bit − 232, otherwise return int32bit.
中文:
- 令
number为调用 ToNumber 将输入参数转化为数值类型的结果- 如果
number是 NaN,+0,-0,+∞ 或者 -∞,返回 +0- 令
posInt为 sign(number) * floor(abs(number))- 将
posInt进行取模处理,转化为在 −2^31 到 2^31−1 之间的 32 位有符号整数并返回- 如果
int32bit大于或等于2^31,则返回int32bit-2^32,否则返回int32bit。从效果上看,ToInt32 依次做了这样几件事:
- 类型转换,非数值类型的需要转化为数值类型
- 特殊值处理,NaN 和 ∞ 都被转化为 0
- 取整,如果是浮点数,会损失小数点后面的精度
- 取模,将整数调整到 32 位有符号整数区间内,如果整数原本不在这个区间,会丧失精度
- 边界处理
~~:将操作数转化为 32 位有符号整数
The production UnaryExpression :
**~**UnaryExpression* is evaluated as follows:中文:
产生式
UnaryExpression : ~~ UnaryExpression按照下面的过程执行:
- 令
expr为解析执行UnaryExpression的结果- 返回 ToInt32(GetValue(
expr))
console.log('2 & 3:', 2 & 3);
console.log('2 | 3:', 2 | 3);
console.log('~3:', ~3);

console.log('~~3:', ~~3);
console.log('~~undefined:', ~~undefined);
console.log('~~null:', ~~null);
console.log('~~true:', ~~true);
console.log('~~false:', ~~false);
console.log('~~{}:', ~~{});
console.log('~~NaN:', ~~NaN);
console.log("~~'':", ~~'');
console.log("~~'test':", ~~'test');
console.log('---------------------');
console.log('~~ (Math.pow(2, 31) - 1):', ~~ (Math.pow(2, 31) - 1));
console.log('~~ (Math.pow(2, 31)):', ~~ (Math.pow(2, 31)));
console.log('~~ (-Math.pow(2, 31)):', ~~ (-Math.pow(2, 31)));
console.log('~~ (-Math.pow(2, 31) - 1):', ~~ (-Math.pow(2, 31) - 1));
console.log('~~ (Math.pow(2, 32)):', ~~ (Math.pow(2, 32)));
console.log('---------------------');
console.log('~~11.7:', ~~11.7);
console.log('~11.7:', ~11.7);
console.log('~~ -11.7:', ~~ -11.7);
console.log('~ -11.7:', ~ -11.7);
console.log('~~11.13:', ~~11.13);
console.log('~11.13:', ~11.13);
console.log('~~ -11.13:', ~~ -11.13);
console.log('~ -11.13:', ~ -11.13);

6. 关系运算符
比较运算符比较二个操作数并返回基于比较结果的Boolean值
> >= < <= == === != !== in instanceof
==,!=与===,!==
等于和全等,他们的区别是,前者会强制类型转换,再比较值。
var a;
console.log('1 == 1:', 1 == 1);
console.log('1 === 1:', 1 === 1);
console.log("1 == '1':", 1 == '1');
console.log("1 === '1':", 1 === '1');
console.log('1 == true:', 1 == true);
console.log('1 === true:', 1 === true);
console.log('0 == false:', 0 == false);
console.log('0 === false:', 0 === false);
console.log('a == undefined:', a == undefined);
console.log('a === undefined:', a === undefined);
console.log('0 == null:', 0 == null);
console.log('0 === null:', 0 === null);
7. 逻辑运算符
逻辑运算符典型的用法是用于boolean(逻辑)值运算, 它们返回boolean值。
&&, ||, !, !!(与,或,非, 双非),
如果一个值可以被转换为 true,那么这个值就是所谓的 truthy,如果可以被转换为 false,那么这个值就是所谓的 falsy。
truthy: 在 JavaScript中,Truthy (真值)指的是在 布尔值 上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为 falsy (即除了 false,0,"",null,undefined 和 NaN 外).
falsy: falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值.
会被转换为 false 的表达式有:
null;NaN;0;空字符串(
""or''or ````);undefined。!: 逻辑非是将当前对象的Boolean取反,即取当前是falsy的值为true,当前是true的值为false。The production UnaryExpression :
**!**UnaryExpression* is evaluated as follows:- Let expr be the result of evaluating UnaryExpression.
- Let oldValue be ToBoolean(GetValue(expr)).
- If oldValue is true, return false.
- Return true.
中文:
产生式
UnaryExpression : ! UnaryExpression按照下面的过程执行:- 令
expr为解析执行UnaryExpression的结果 - 令
oldValue为 ToBoolean(GetValue(expr)) - 如果
oldValue为 true, 返回 false - 返回 true
!!: 将操作数转化为布尔类型The production UnaryExpression :
**!!**UnaryExpression* is evaluated as follows:中文:
产生式
UnaryExpression : !! UnaryExpression按照下面的过程执行:- 令
expr为解析执行UnaryExpression的结果 - 返回 ToBoolean(GetValue(
expr))
由于逻辑表达式的运算的顺序是从左到右,也可以用以下规则进行"短路"计算,
console.log(true && true);
console.log(true && false);
console.log(false && false);
console.log(true || true);
console.log(true || false);
console.log(false && true);
// 逻辑表达式从左往右运算
console.log(true && false || true);
console.log(true && true || false);
console.log(false && false || true);
console.log(true && true || false);
console.log(true && true || true);

console.log('!true', !true);
console.log('!false', !false);
console.log('!1', !1);
console.log('!0', !0);
console.log('!!true', !!true);
console.log('!!false', !!false);
console.log('!!null', !!null);
console.log('!!undefiend', !!undefined);
console.log('!!1', !!1);
console.log('!!0', !!0);
console.log("!!''", !!'');
console.log("!!'test'", !!'test');
console.log('!!{}', !!{});
8. 条件(三元)运算符
?:: 是 JavaScript 仅有的使用三个操作数的运算符。本运算符经常作为if语句的简短形式来使用。
console.log(true ? 'true' : 'false');
console.log(false ? 'true' : 'false');
// 多个条件判断
console.log(true ? 'true' : true ? 'false true' : 'false');
console.log(false ? 'true' : true ? 'false true' : 'false');

9. 赋值运算符
= += -= *= /= %= **=(平方) <<= >>= >>>= &= |= ^|
10. 可选链
var a = {};
console.log(a?.b);
var a = { b: 1 };
console.log(a?.b);
参考