运算符

掌握JavaScript中的各类运算操作

运算符概述

运算符用于对值执行操作。JavaScript支持多种类型的运算符:

  • 算术运算符 - 执行数学运算
  • 赋值运算符 - 为变量赋值
  • 比较运算符 - 比较值的大小
  • 逻辑运算符 - 组合布尔值
  • 位运算符 - 操作二进制位
  • 字符串运算符 - 连接字符串
  • 条件运算符 - 基于条件选择值
  • 类型运算符 - 检查变量类型
  • 其他运算符 - 逗号、delete、void等

运算符分类

根据操作数的数量,运算符可以分为:

  • 一元运算符 - 操作一个操作数,如:++, --, !, typeof
  • 二元运算符 - 操作两个操作数,如:+, -, *, /, &&
  • 三元运算符 - 操作三个操作数,如:? :

算术运算符

用于执行基本的数学运算:

运算符 描述 示例 结果
+ 加法 5 + 3 8
- 减法 5 - 3 2
* 乘法 5 * 3 15
/ 除法 15 / 3 5
% 取模(余数) 10 % 3 1
** 指数(ES2016) 2 ** 3 8
++ 递增 x++ x + 1
-- 递减 x-- x - 1
+ (一元) 一元加 +"5" 5
- (一元) 一元减 -5 -5
算术运算符示例
let a = 10, b = 3;

console.log(a + b);   // 13
console.log(a - b);   // 7
console.log(a * b);   // 30
console.log(a / b);   // 3.333...
console.log(a % b);   // 1
console.log(a ** b);  // 1000

// 递增和递减
let x = 5;
console.log(x++);     // 5 (后置递增)
console.log(x);       // 6
console.log(++x);     // 7 (前置递增)

// 一元加减运算符
console.log(+"5");     // 5 (字符串转数字)
console.log(-"5");     // -5
console.log(+true);   // 1
console.log(+false);  // 0
注意: 递增和递减运算符有前置和后置之分。前置运算符先进行运算再返回值,后置运算符先返回值再进行运算。

赋值运算符

用于为变量赋值:

运算符 示例 等价于
= x = y x = y
+= x += y x = x + y
-= x -= y x = x - y
*= x *= y x = x * y
/= x /= y x = x / y
%= x %= y x = x % y
**= x **= y x = x ** y
&= x &= y x = x & y
|= x |= y x = x | y
^= x ^= y x = x ^ y
<<= x <<= y x = x << y
>>= x >>= y x = x >> y
>>>= x >>>= y x = x >>> y
赋值运算符示例
let x = 10;

x += 5;   // x = 15
x -= 3;   // x = 12
x *= 2;   // x = 24
x /= 4;   // x = 6
x %= 4;   // x = 2
x **= 3;  // x = 8

// 字符串连接
let str = "Hello";
str += " World";  // "Hello World"

// 解构赋值 (ES6)
let [a, b] = [1, 2];  // a = 1, b = 2
let {name, age} = {name: "John", age: 30};  // name = "John", age = 30

比较运算符

用于比较值,返回布尔值:

运算符 描述 示例 结果
== 等于(宽松) 5 == "5" true
=== 等于(严格) 5 === "5" false
!= 不等于(宽松) 5 != "6" true
!== 不等于(严格) 5 !== "5" true
> 大于 5 > 3 true
< 小于 5 < 3 false
>= 大于等于 5 >= 5 true
<= 小于等于 5 <= 3 false
比较运算符示例
console.log(5 == "5");     // true (类型转换)
console.log(5 === "5");    // false (类型不同)
console.log(5 != "6");     // true
console.log(5 !== "5");    // true

console.log(10 > 5);      // true
console.log(10 < 5);      // false
console.log(10 >= 10);     // true
console.log(10 <= 5);     // false

// 特殊比较
console.log(null == undefined);  // true
console.log(null === undefined); // false
console.log(NaN == NaN);        // false (特殊规则)
console.log(NaN === NaN);       // false
console.log(0 == false);        // true
console.log("" == false);       // true
console.log("0" == false);      // true
最佳实践: 总是使用严格相等(===)和严格不相等(!==)运算符,避免类型转换带来的意外行为。

对象比较的特殊情况

对象比较
// 对象比较的是引用,而不是内容
let obj1 = { value: 10 };
let obj2 = { value: 10 };
let obj3 = obj1;

console.log(obj1 == obj2);   // false (不同对象)
console.log(obj1 === obj2);  // false (不同对象)
console.log(obj1 == obj3);   // true (相同引用)
console.log(obj1 === obj3);  // true (相同引用)

逻辑运算符

用于组合或反转布尔值:

运算符 描述 示例 结果
&& 逻辑与 true && false false
|| 逻辑或 true || false true
! 逻辑非 !true false
?? (ES2020) 空值合并 null ?? "默认" "默认"
逻辑运算符示例
// 基本逻辑运算
console.log(true && true);    // true
console.log(true && false);   // false
console.log(true || false);   // true
console.log(false || false);  // false
console.log(!true);           // false
console.log(!false);          // true

// 短路求值
let result1 = true && "Hello";   // "Hello"
let result2 = false && "Hello";  // false
let result3 = true || "Hello";    // true
let result4 = false || "Hello";   // "Hello"

// 复杂逻辑表达式
let age = 25;
let hasLicense = true;
let canDrive = age >= 18 && hasLicense;  // true

// 空值合并运算符 (??)
let value1 = null ?? "默认值";        // "默认值"
let value2 = undefined ?? "默认值";  // "默认值"
let value3 = 0 ?? "默认值";           // 0
let value4 = "" ?? "默认值";          // ""
注意: 空值合并运算符 (??) 与逻辑或 (||) 的区别在于,?? 只在值为 null 或 undefined 时使用默认值,而 || 会在任何假值(0, "", false 等)时使用默认值。

位运算符

位运算符对操作数的二进制表示进行操作:

运算符 描述 示例 结果
& 按位与 5 & 1 1
| 按位或 5 | 1 5
^ 按位异或 5 ^ 1 4
~ 按位非 ~5 -6
<< 左移 5 << 1 10
>> 右移 5 >> 1 2
>>> 无符号右移 -5 >>> 1 2147483645
位运算符示例
// 按位与
console.log(5 & 1);   // 1 (0101 & 0001 = 0001)

// 按位或
console.log(5 | 1);   // 5 (0101 | 0001 = 0101)

// 按位异或
console.log(5 ^ 1);   // 4 (0101 ^ 0001 = 0100)

// 按位非
console.log(~5);      // -6 (~00000000000000000000000000000101 = 11111111111111111111111111111010)

// 左移
console.log(5 << 1);  // 10 (0101 << 1 = 1010)

// 右移
console.log(5 >> 1);  // 2 (0101 >> 1 = 0010)

// 无符号右移
console.log(-5 >>> 1); // 2147483645

其他运算符

条件(三元)运算符

三元运算符
// 语法: condition ? expr1 : expr2
let age = 20;
let status = age >= 18 ? "成年人" : "未成年人";
console.log(status);  // "成年人"

// 嵌套三元运算符
let score = 85;
let grade = score >= 90 ? "A" : 
             score >= 80 ? "B" : 
             score >= 70 ? "C" : "D";
console.log(grade);   // "B"

// 与逻辑运算符结合使用
let name = null;
let displayName = name ? name : "匿名用户";
// 等价于: let displayName = name || "匿名用户";

类型运算符

类型运算符
console.log(typeof "hello");     // "string"
console.log(typeof 42);          // "number"
console.log(typeof true);        // "boolean"
console.log(typeof undefined);   // "undefined"
console.log(typeof null);        // "object" (历史遗留问题)
console.log(typeof {});          // "object"
console.log(typeof []);          // "object"
console.log(typeof function(){}); // "function"

let arr = [1, 2, 3];
console.log(Array.isArray(arr));  // true
console.log(arr instanceof Array);  // true

function Person() {}
let person = new Person();
console.log(person instanceof Person);  // true

其他特殊运算符

其他运算符
// 逗号运算符 - 从左到右求值,返回最后一个值
let x = (1, 2, 3);  // x = 3

// void 运算符 - 计算表达式并返回 undefined
let result = void 5;  // result = undefined

// delete 运算符 - 删除对象属性
let obj = { a: 1, b: 2 };
delete obj.a;
console.log(obj);  // { b: 2 }

// in 运算符 - 检查属性是否存在
console.log("b" in obj);  // true
console.log("a" in obj);  // false

运算符优先级

运算符按照优先级顺序执行:

优先级 运算符 描述 结合性
21 () 分组 不适用
20 . [] new () 成员访问、计算成员访问、new(带参数列表) 从左到右
19 () 函数调用 从左到右
18 new new(无参数列表) 从右到左
17 ++ -- 后置递增、后置递减 不适用
16 ! ~ +(一元) -(一元) ++ -- typeof void delete 逻辑非、按位非、一元加减、前置递增递减、typeof、void、delete 从右到左
15 ** 指数 从右到左
14 * / % 乘法、除法、取模 从左到右
13 + - 加法、减法 从左到右
12 << >> >>> 位移 从左到右
11 < <= > >= in instanceof 关系、in、instanceof 从左到右
10 == != === !== 相等性 从左到右
9 & 按位与 从左到右
8 ^ 按位异或 从左到右
7 | 按位或 从左到右
6 && 逻辑与 从左到右
5 || ?? 逻辑或、空值合并 从左到右
4 ? : 条件运算符 从右到左
3 = += -= 赋值 从右到左
2 yield yield* yield 从右到左
1 , 逗号 从左到右
优先级示例
// 乘法优先于加法
let result1 = 2 + 3 * 4;     // 14 (不是20)

// 使用括号改变优先级
let result2 = (2 + 3) * 4;   // 20

// 逻辑运算符优先级: ! > && > ||
let a = true, b = false, c = true;
let result3 = a || b && c;     // true (相当于 a || (b && c))
let result4 = (a || b) && c;   // true

// 指数运算符是右结合的
let result5 = 2 ** 3 ** 2;    // 512 (相当于 2 ** (3 ** 2))
let result6 = (2 ** 3) ** 2;  // 64
建议: 当表达式复杂时,使用括号明确优先级,提高代码可读性。

实践练习

👆 请点击上方按钮进行演示操作

选择不同的演示按钮来探索JavaScript的各种功能和用法

练习代码
// 练习1: 复合运算
let x = 10, y = 3;
let result = (x + y) * (x - y) / y;
console.log(result);  // 30.333...

// 练习2: 逻辑判断
let age = 25;
let hasID = true;
let hasTicket = false;
let canEnter = (age >= 18 && hasID) || hasTicket;
console.log(canEnter);  // true

// 练习3: 三元运算符
let temperature = 22;
let clothing = temperature > 20 ? "T恤" : "外套";
console.log(clothing);  // "T恤"

// 练习4: 位运算应用
let num = 13;  // 二进制: 1101
let isEven = (num & 1) === 0;  // 检查是否为偶数
console.log(isEven);  // false

// 练习5: 运算符优先级理解
let a = 5, b = 3, c = 2;
let complexResult = a + b * c ** 2 / (a - b);
console.log(complexResult);  // 14

常见问题与解答

1. 为什么应该使用 === 而不是 ==?

严格相等运算符 (===) 不会进行类型转换,行为更可预测。宽松相等运算符 (==) 会进行类型转换,可能导致意外的结果,例如:

== 的意外行为
console.log(0 == false);     // true
console.log("" == false);    // true
console.log(null == undefined); // true

2. 递增/递减运算符的前置和后置有什么区别?

前置运算符先进行运算再返回值,后置运算符先返回值再进行运算:

前置 vs 后置
let a = 5;
console.log(a++);  // 5 (先返回值,再递增)
console.log(a);    // 6

let b = 5;
console.log(++b);  // 6 (先递增,再返回值)
console.log(b);    // 6

3. 什么时候使用位运算符?

位运算符主要用于:

  • 性能优化(某些位运算比算术运算更快)
  • 处理二进制数据
  • 实现特定的算法(如哈希函数、加密算法)
  • 标志位操作

最佳实践

  • 使用严格相等运算符 (=== 和 !==) 避免类型转换问题
  • 在复杂表达式中使用括号明确优先级
  • 避免使用位运算符处理非整数,因为会先转换为32位整数
  • 谨慎使用递增/递减运算符,注意前置和后置的区别
  • 使用空值合并运算符 (??) 代替逻辑或 (||) 设置默认值,避免0和""被当作假值
  • 避免使用eval()函数,它存在安全风险

下一步学习

掌握了运算符后,接下来可以学习: