你真的会使用这些运算符吗?
个人主页:康师傅前端面馆
在 Stack Overflow 上,每天有上千个提问源于对
++、+=或=+的误解;面试里,一段看似简单的x++ + ++x就能让候选人当场沉默。本文用 5 分钟带你彻底搞懂这些“老熟人”——自增、自减与复合赋值运算符——到底做了什么、何时做、以及怎样避免那些隐藏的地雷。读完你会发现,它们不仅能让代码更短,也能让 Bug 更少。
1. 自增自减运算符 (++ / --)
1.1 基本概念
自增 (++) 和自减 (--) 是一元运算符,用于将变量的值增加或减少 1。
1.2 前缀形式 vs 后缀形式
- 前缀形式:先增加/减少变量的值,然后返回新值
- 后缀形式:先返回原值,然后增加/减少变量的值
let a = 5;
let b = 5;
// 前缀形式
console.log(++a); // 输出: 6 (先增加,再返回)
console.log(a); // 输出: 6
// 后缀形式
console.log(b++); // 输出: 5 (先返回,再增加)
console.log(b); // 输出: 6
1.3 注意事项
- 只能应用于变量,不能用于字面量或表达式
- 对于非数值类型的变量,会尝试转换为数字后再进行运算
let str = "5";
console.log(++str); // 输出: 6 (字符串 "5" 转换为数字 5 后加 1)
let bool = true;
console.log(++bool); // 输出: 2 (布尔值 true 转换为数字 1 后加 1)
1.4 易出错点
// 错误示例 - 不能用于字面量
++5; // SyntaxError: Invalid left-hand side expression in prefix operation
// 复杂表达式中的行为可能令人困惑
// 先计算后赋值
let a = 1;
let b = ++a;
console.log(a); // 输出: 2
console.log(b); // 输出: 2
// 先赋值后计算
let a = 1;
let b = a++;
console.log(a); // 输出: 2
console.log(b); // 输出: 1
// 混合运算
let x = 1;
let y = ++x + x++; // 结果是 4,因为:
// 1. ++x 先将 x 增加到 2,表达式的这部分值为 2
// 2. x++ 使用当前 x 的值 2,然后将 x 增加到 3
// 3. 最终结果是 2 + 2 = 4
console.log(y); // 输出: 4
console.log(x); // 输出: 3
2. 复合赋值运算符 (+=, -=, *=, /=, %=, **= 等)
2.1 基本概念
复合赋值运算符是赋值运算符和算术运算符的组合,使代码更加简洁。
2.2 += 运算符
+= 运算符将右操作数加到左操作数上,并将结果赋值给左操作数。
let a = 5;
a += 3; // 等价于 a = a + 3
console.log(a); // 输出: 8
// 字符串连接
let str = "Hello";
str += " World"; // 等价于 str = str + " World"
console.log(str); // 输出: "Hello World"
2.3 其他复合赋值运算符
let x = 10;
x -= 3; // 等价于 x = x - 3; 结果: 7
x *= 2; // 等价于 x = x * 2; 结果: 14
x /= 2; // 等价于 x = x / 2; 结果: 7
x %= 3; // 等价于 x = x % 3; 结果: 1
x **= 3; // 等价于 x = x ** 3; 结果: 1
2.4 注意事项
- 左操作数必须是可赋值的引用(变量、对象属性等)
- 右操作数会被转换为适当的类型进行运算
let obj = { value: 5 };
obj.value += 10; // 对象属性也可以使用复合赋值运算符
console.log(obj.value); // 输出: 15
3. =+ 运算符误解澄清
3.1 实际含义
=+ 并不是一个独立的运算符,而是赋值运算符 = 和一元正号运算符 + 的组合。
let a = "5";
let b = +a; // 将字符串 "5" 转换为数字 5
console.log(b); // 输出: 5
console.log(typeof b); // 输出: "number"
// 等价于
let c = Number(a);
// 或
let d = parseInt(a);
3.2 常见用途
常用于将字符串转换为数字:
let userInput = "123";
let number = +userInput; // 快速转换为数字
// 在表单处理中很常见
let ageInput = document.getElementById("age").value; // 字符串
let age = +ageInput; // 转换为数字
3.3 特殊情况
console.log(+"5"); // 输出: 5
console.log(+"3.14"); // 输出: 3.14
console.log(+"hello"); // 输出: NaN
console.log(+true); // 输出: 1
console.log(+false); // 输出: 0
console.log(+null); // 输出: 0
console.log(+undefined); // 输出: NaN
4. 运算符优先级
了解运算符优先级对于正确编写表达式至关重要:
let a = 2;
let b = 3;
// ** 运算符优先级高于乘法
console.log(2 * 3 ** 2); // 输出: 18 (等价于 2 * (3 ** 2))
// ++ 前缀形式优先级高于 +
let x = 1;
let y = 2;
console.log(++x + y); // 输出: 4 (等价于 (++x) + y)
// += 优先级低于大多数运算符
let z = 5;
z *= 2 + 3; // 等价于 z = z * (2 + 3),结果是 25
5. 最佳实践建议
5.1 提高代码可读性
// 好的做法:清晰易懂
let counter = 0;
counter++;
counter += 5;
// 避免过于复杂的表达式
let result = ++a + b++ * c--; // 难以理解
5.2 注意类型转换
// 明确意图,避免隐式转换带来的困惑
let numStr = "10";
let result = +numStr + 5; // 明确转换为数字后相加,结果为 15
// 而不是
let result2 = numStr + 5; // 字符串连接,结果为 "105"
5.3 避免副作用
// 避免在一个表达式中多次使用 ++/-- 修改同一变量
let x = 1;
let y = x++ + x++; // 不推荐,行为难以预测
// 更清晰的写法
let y = x + (x + 1);
x += 2;