运算符与表达式
本章将详细介绍ECMAScript中的各种运算符和表达式,包括算术运算符、比较运算符、逻辑运算符等,以及它们的优先级和结合性。
6.1 运算符概述
运算符是用于执行程序代码运算的符号,它们可以对一个或多个操作数进行操作并产生结果。ECMAScript提供了丰富的运算符来满足不同的运算需求。
6.2 算术运算符
算术运算符用于执行基本的数学运算。
基本算术运算符
// 加法
let sum = 5 + 3; // 8
// 减法
let difference = 10 - 4; // 6
// 乘法
let product = 7 * 6; // 42
// 除法
let quotient = 15 / 3; // 5
// 取余
let remainder = 17 % 5; // 2
// 指数运算 (ES2016)
let power = 2 ** 3; // 8
递增和递减运算符
// 前置递增
let a = 5;
let b = ++a; // a = 6, b = 6
// 后置递增
let c = 5;
let d = c++; // c = 6, d = 5
// 前置递减
let e = 10;
let f = --e; // e = 9, f = 9
// 后置递减
let g = 10;
let h = g--; // g = 9, h = 10
一元运算符
// 正号
let positive = +5; // 5
// 负号
let negative = -5; // -5
// 类型转换
let str = "123";
let num = +str; // 123 (转换为数字)
// 逻辑非
let truthy = !"hello"; // false
let falsy = !0; // true
6.3 比较运算符
比较运算符用于比较两个值并返回布尔值。
相等比较运算符
// 相等 (==) - 进行类型转换
console.log(5 == "5"); // true
console.log(true == 1); // true
console.log(null == undefined); // true
// 不相等 (!=) - 进行类型转换
console.log(5 != "6"); // true
// 严格相等 (===) - 不进行类型转换
console.log(5 === 5); // true
console.log(5 === "5"); // false
// 严格不相等 (!==) - 不进行类型转换
console.log(5 !== "5"); // true
关系比较运算符
// 大于
console.log(5 > 3); // true
// 小于
console.log(3 < 5); // true
// 大于等于
console.log(5 >= 5); // true
// 小于等于
console.log(3 <= 5); // true
6.4 逻辑运算符
逻辑运算符用于组合多个布尔值表达式。
基本逻辑运算符
// 逻辑与 (&&)
let andResult = true && false; // false
let andResult2 = "hello" && 42; // 42 (短路求值)
// 逻辑或 (||)
let orResult = true || false; // true
let orResult2 = "" || "default"; // "default" (短路求值)
// 逻辑非 (!)
let notResult = !true; // false
let notResult2 = !"hello"; // false
空值合并运算符 (??) - ES2020
// 只有当左侧为null或undefined时才返回右侧值
let value1 = null ?? "default"; // "default"
let value2 = "" ?? "default"; // "" (空字符串不是null或undefined)
let value3 = 0 ?? "default"; // 0 (0不是null或undefined)
可选链运算符 (?.) - ES2020
// 安全访问嵌套属性
let user = {
name: "张三",
address: {
city: "北京"
}
};
let city = user?.address?.city; // "北京"
let country = user?.address?.country; // undefined (不会报错)
let phone = user?.phone?.number; // undefined (不会报错)
6.5 位运算符
位运算符用于对数字的二进制表示进行操作。
// 按位与 (&)
let and = 5 & 3; // 1 (101 & 011 = 001)
// 按位或 (|)
let or = 5 | 3; // 7 (101 | 011 = 111)
// 按位异或 (^)
let xor = 5 ^ 3; // 6 (101 ^ 011 = 110)
// 按位非 (~)
let not = ~5; // -6
// 左移 (<<)
let leftShift = 5 << 1; // 10 (101 << 1 = 1010)
// 右移 (>>)
let rightShift = 5 >> 1; // 2 (101 >> 1 = 10)
// 无符号右移 (>>>)
let unsignedRightShift = -5 >>> 1; // 2147483645
6.6 赋值运算符
赋值运算符用于给变量赋值。
基本赋值运算符
// 简单赋值
let x = 10;
// 复合赋值运算符
x += 5; // x = x + 5
x -= 3; // x = x - 3
x *= 2; // x = x * 2
x /= 4; // x = x / 4
x %= 3; // x = x % 3
x **= 2; // x = x ** 2 (ES2016)
x <<= 1; // x = x << 1
x >>= 1; // x = x >> 1
x >>>= 1; // x = x >>> 1
x &= 3; // x = x & 3
x |= 3; // x = x | 3
x ^= 3; // x = x ^ 3
6.7 运算符优先级
运算符优先级决定了表达式中运算的执行顺序。优先级高的运算符会先执行。
优先级示例
// 乘法优先级高于加法
let result1 = 2 + 3 * 4; // 14 (先算3*4=12,再算2+12=14)
// 使用括号改变优先级
let result2 = (2 + 3) * 4; // 20 (先算2+3=5,再算5*4=20)
// 逻辑运算符优先级
let result3 = true || false && false; // true (&&优先级高于||)
常用运算符优先级表
优先级 | 运算符 | 结合性 |
---|---|---|
20 | () [] . | 从左到右 |
19 | ++ -- (后置) | 从左到右 |
18 | ++ -- (前置) ! ~ + - typeof void delete | 从右到左 |
17 | ** (指数) | 从右到左 |
16 | * / % | 从左到右 |
15 | + - | 从左到右 |
12 | <> <=>= | 从左到右 |
11 | == != === !== | 从左到右 |
7 | && | 从左到右 |
6 | || | 从左到右 |
4 | ? : | 从右到左 |
3 | = += -= *= /= %= **= <<=>>= &= ^= |= | 从右到左 |
6.8 表达式
表达式是由变量、常量、运算符和函数调用组成的代码片段,它会产生一个值。
表达式类型
// 算术表达式
let arithmetic = 5 + 3 * 2;
// 字符串表达式
let stringExpr = "Hello" + " " + "World";
// 逻辑表达式
let logical = (5 > 3) && (2 < 4);
// 函数调用表达式
let funcResult = Math.max(5, 10, 3);
// 对象创建表达式
let obj = {name: "张三", age: 25};
// 数组创建表达式
let arr = [1, 2, 3, 4];
// 条件表达式 (三元运算符)
let status = age >= 18 ? "成年人" : "未成年人";
6.9 运算符的实际应用
条件赋值
// 使用逻辑或设置默认值
let userName = inputName || "匿名用户";
// 使用空值合并运算符设置默认值
let userAge = inputAge ?? 18;
// 使用三元运算符进行条件赋值
let discount = isMember ? 0.1 : 0;
链式操作
// 方法链
let result = [1, 2, 3, 4, 5]
.filter(x => x > 2) // [3, 4, 5]
.map(x => x * 2) // [6, 8, 10]
.reduce((a, b) => a + b, 0); // 24
提示:理解运算符的优先级和结合性对于编写正确的表达式非常重要。在复杂的表达式中,适当使用括号可以提高代码的可读性和可维护性。