JavaScript 运算符
运算符是 JavaScript 中执行特定数学、逻辑或赋值操作的符号。理解各种运算符的用法和优先级对于编写正确的 JavaScript 代码至关重要。在本章节中,我们将深入学习 JavaScript 中的各种运算符及其使用方法。
什么是运算符
运算符是用于执行特定操作的符号,它们可以对一个或多个操作数进行操作。操作数可以是变量、常量或表达式。
javascript
let x = 5 + 3; // + 是运算符,5 和 3 是操作数
let y = x * 2; // * 是运算符,x 和 2 是操作数运算符的分类
JavaScript 中的运算符可以按照不同的标准进行分类:
按操作数数量分类
- 一元运算符:只需要一个操作数
- 二元运算符:需要两个操作数
- 三元运算符:需要三个操作数
按功能分类
- 算术运算符
- 赋值运算符
- 比较运算符
- 逻辑运算符
- 位运算符
- 字符串运算符
- 条件(三元)运算符
- 逗号运算符
- 一元运算符
- 关系运算符
算术运算符
算术运算符用于执行基本的数学运算。
javascript
let a = 10;
let b = 3;
// 加法
console.log(a + b); // 13
// 减法
console.log(a - b); // 7
// 乘法
console.log(a * b); // 30
// 除法
console.log(a / b); // 3.3333333333333335
// 取模(求余数)
console.log(a % b); // 1
// 幂运算(ES2016)
console.log(a ** b); // 1000 (10的3次方)
// 递增
let c = 5;
console.log(++c); // 6 (前置递增)
console.log(c++); // 6 (后置递增)
console.log(c); // 7
// 递减
let d = 5;
console.log(--d); // 4 (前置递减)
console.log(d--); // 4 (后置递减)
console.log(d); // 3
// 一元加法(转换为数字)
console.log(+"5"); // 5
console.log(+"hello"); // NaN
// 一元减法(转换为负数)
console.log(-"5"); // -5
console.log(-"hello"); // NaN赋值运算符
赋值运算符用于给变量赋值。
javascript
let x = 10;
// 基本赋值
x = 5; // x = 5
// 加法赋值
x += 3; // x = x + 3 = 8
// 减法赋值
x -= 2; // x = x - 2 = 6
// 乘法赋值
x *= 4; // x = x * 4 = 24
// 除法赋值
x /= 3; // x = x / 3 = 8
// 取模赋值
x %= 5; // x = x % 5 = 3
// 幂赋值(ES2016)
x **= 2; // x = x ** 2 = 9
// 左移赋值
x <<= 1; // x = x << 1 = 18
// 右移赋值
x >>= 1; // x = x >> 1 = 9
// 无符号右移赋值
x >>>= 1; // x = x >>> 1 = 4
// 按位与赋值
x &= 3; // x = x & 3 = 0
// 按位异或赋值
x ^= 5; // x = x ^ 5 = 5
// 按位或赋值
x |= 2; // x = x | 2 = 7
// 逻辑与赋值(ES2020)
let obj = {};
obj &&= "有值"; // obj = obj && "有值" = "有值"
// 逻辑或赋值(ES2020)
let value = null;
value ||= "默认值"; // value = value || "默认值" = "默认值"
// 空值合并赋值(ES2020)
let data = null;
data ??= "默认数据"; // data = data ?? "默认数据" = "默认数据"比较运算符
比较运算符用于比较两个值,返回布尔值(true 或 false)。
javascript
let a = 5;
let b = "5";
let c = 10;
// 相等
console.log(a == b); // true (类型转换后相等)
console.log(a === b); // false (严格相等,不进行类型转换)
// 不相等
console.log(a != b); // false (类型转换后相等)
console.log(a !== b); // true (严格不相等)
// 大于
console.log(c > a); // true
// 小于
console.log(a < c); // true
// 大于等于
console.log(c >= a); // true
// 小于等于
console.log(a <= c); // true
// 特殊比较情况
console.log(null == undefined); // true
console.log(null === undefined); // false
console.log(NaN == NaN); // false
console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true逻辑运算符
逻辑运算符用于组合多个布尔表达式。
javascript
let x = true;
let y = false;
let a = 5;
let b = 0;
// 逻辑与 (&&)
console.log(x && y); // false
console.log(a && b); // 0 (短路求值)
console.log(a && "hello"); // "hello"
// 逻辑或 (||)
console.log(x || y); // true
console.log(b || a); // 5 (短路求值)
console.log(b || "default"); // "default"
// 逻辑非 (!)
console.log(!x); // false
console.log(!b); // true
console.log(!!a); // true (双重否定转换为布尔值)
// 空值合并运算符 (??) - ES2020
console.log(null ?? "default"); // "default"
console.log(undefined ?? "default"); // "default"
console.log("" ?? "default"); // ""
console.log(0 ?? "default"); // 0
// 逻辑空赋值 (??=) - ES2020
let config = { theme: null };
config.theme ??= "light";
console.log(config.theme); // "light"位运算符
位运算符对数字的二进制表示进行操作。
javascript
let a = 5; // 二进制: 101
let b = 3; // 二进制: 011
// 按位与 (&)
console.log(a & b); // 1 (二进制: 001)
// 按位或 (|)
console.log(a | b); // 7 (二进制: 111)
// 按位异或 (^)
console.log(a ^ b); // 6 (二进制: 110)
// 按位非 (~)
console.log(~a); // -6 (二进制: ...11111010)
// 左移 (<<)
console.log(a << 1); // 10 (二进制: 1010)
// 右移 (>>)
console.log(a >> 1); // 2 (二进制: 10)
// 无符号右移 (>>>)
console.log(a >>> 1); // 2 (对于正数与 >> 相同)字符串运算符
JavaScript 中的字符串运算符主要是连接运算符。
javascript
// 字符串连接
let firstName = "张";
let lastName = "三";
let fullName = firstName + lastName; // "张三"
// 字符串与数字连接
let age = 25;
let message = "我今年" + age + "岁"; // "我今年25岁"
// 复合赋值连接
let greeting = "你好";
greeting += ",世界!"; // "你好,世界!"
// 模板字符串(ES6)
let name = "李四";
let template = `你好,${name}!`; // "你好,李四!"条件(三元)运算符
三元运算符是 if...else 语句的简写形式。
javascript
let age = 18;
// 基本用法
let status = age >= 18 ? "成年人" : "未成年人";
console.log(status); // "成年人"
// 嵌套三元运算符
let score = 85;
let grade = score >= 90 ? "优秀" :
score >= 80 ? "良好" :
score >= 70 ? "中等" :
score >= 60 ? "及格" : "不及格";
console.log(grade); // "良好"
// 在函数调用中使用
function getDiscount(isMember) {
return isMember ? 0.1 : 0;
}
let discount = getDiscount(true); // 0.1
// 在对象属性中使用
let user = {
name: "张三",
role: "admin",
permissions: user.role === "admin" ? ["read", "write", "delete"] : ["read"]
};逗号运算符
逗号运算符允许在一条语句中执行多个表达式。
javascript
// 基本用法
let a = (1, 2, 3); // a = 3 (返回最后一个表达式的值)
// 在 for 循环中使用
for (let i = 0, j = 10; i < 5; i++, j--) {
console.log(`i: ${i}, j: ${j}`);
}
// 复杂表达式
let x = (console.log("第一个表达式"),
console.log("第二个表达式"),
"最终值");
console.log(x); // "最终值"一元运算符
一元运算符只需要一个操作数。
javascript
let a = 5;
// delete 运算符
let obj = { name: "张三", age: 25 };
delete obj.age;
console.log(obj); // { name: "张三" }
// typeof 运算符
console.log(typeof a); // "number"
console.log(typeof "hello"); // "string"
console.log(typeof true); // "boolean"
console.log(typeof undefined); // "undefined"
console.log(typeof null); // "object" (JavaScript 的历史遗留问题)
// void 运算符
let result = void 0; // undefined
console.log(result); // undefined
// in 运算符
let person = { name: "张三", age: 25 };
console.log("name" in person); // true
console.log("salary" in person); // false
// instanceof 运算符
let arr = [1, 2, 3];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true运算符优先级
运算符优先级决定了表达式中运算符的执行顺序。
javascript
// 优先级示例
let result1 = 3 + 4 * 5; // 23 (乘法优先级高于加法)
let result2 = (3 + 4) * 5; // 35 (括号优先级最高)
// 相同优先级的运算符(从左到右)
let result3 = 10 - 5 - 2; // 3 (从左到右计算)
// 赋值运算符(从右到左)
let a, b, c;
a = b = c = 5; // a = b = c = 5
// 逻辑运算符的短路求值
let x = null;
let y = x && x.length; // null (不会执行 x.length)
let z = x || "默认值"; // "默认值"运算符结合性
当运算符优先级相同时,结合性决定了运算顺序。
javascript
// 左结合性
let result1 = 10 - 5 - 2; // (10 - 5) - 2 = 3
// 右结合性
let a, b, c;
a = b = c = 5; // a = (b = (c = 5))
// 三元运算符的右结合性
let grade = score >= 90 ? "A" :
score >= 80 ? "B" :
score >= 70 ? "C" : "D";类型转换和运算符
运算符经常涉及类型转换。
javascript
// 隐式类型转换
console.log("5" + 3); // "53" (字符串连接)
console.log("5" - 3); // 2 (数值运算)
console.log(true + 1); // 2 (true 转换为 1)
console.log(false + 1); // 1 (false 转换为 0)
console.log("5" * "3"); // 15 (字符串转换为数字)
// 显式类型转换
console.log(Number("5") + 3); // 8
console.log(String(5) + 3); // "53"
console.log(Boolean(0)); // false
// 比较运算符的类型转换
console.log(0 == ""); // true
console.log(0 == "0"); // true
console.log(false == "0"); // true
console.log(null == undefined); // true运算符的最佳实践
1. 使用严格相等运算符
javascript
// 推荐:使用严格相等
if (value === null) {
// 处理 null
}
if (value === undefined) {
// 处理 undefined
}
// 不推荐:使用宽松相等
// if (value == null) {
// // 同时匹配 null 和 undefined
// }2. 合理使用短路求值
javascript
// 安全访问对象属性
let user = getUser();
let name = user && user.profile && user.profile.name;
// 使用可选链(ES2020)
let name2 = user?.profile?.name;
// 默认值设置
let config = getConfig() || defaultConfig;
// 使用空值合并运算符(ES2020)
let config2 = getConfig() ?? defaultConfig;3. 注意运算符优先级
javascript
// 使用括号明确意图
let result1 = (a + b) * c; // 明确
let result2 = a + b * c; // 容易误解
// 复杂表达式使用括号
let isValid = (user.age >= 18) && (user.isActive || user.isAdmin);4. 避免过度使用三元运算符
javascript
// 简单情况使用三元运算符
let status = age >= 18 ? "成年人" : "未成年人";
// 复杂情况使用 if...else
if (score >= 90) {
grade = "A";
} else if (score >= 80) {
grade = "B";
} else if (score >= 70) {
grade = "C";
} else {
grade = "D";
}
// 而不是:
// let grade = score >= 90 ? "A" :
// score >= 80 ? "B" :
// score >= 70 ? "C" : "D";实际应用示例
1. 数学计算工具
javascript
class Calculator {
// 安全除法
static divide(a, b) {
if (b === 0) {
throw new Error("除数不能为零");
}
return a / b;
}
// 百分比计算
static percentage(value, total) {
return total !== 0 ? (value / total) * 100 : 0;
}
// 范围检查
static inRange(value, min, max) {
return value >= min && value <= max;
}
// 数值格式化
static formatNumber(num, decimals = 2) {
return Number(num.toFixed(decimals));
}
// 安全数值转换
static toNumber(value, defaultValue = 0) {
const num = Number(value);
return isNaN(num) ? defaultValue : num;
}
}
// 使用示例
console.log(Calculator.divide(10, 2)); // 5
console.log(Calculator.percentage(25, 100)); // 25
console.log(Calculator.inRange(5, 1, 10)); // true
console.log(Calculator.formatNumber(3.14159, 2)); // 3.14
console.log(Calculator.toNumber("123.45")); // 123.452. 字符串处理工具
javascript
class StringOperations {
// 安全字符串连接
static concat(...strings) {
return strings.filter(str => str != null).join("");
}
// 字符串重复
static repeat(str, times) {
return str.repeat(Math.max(0, times || 0));
}
// 字符串填充
static pad(str, length, char = " ", position = "left") {
str = String(str);
if (str.length >= length) return str;
const padLength = length - str.length;
const padding = char.repeat(Math.ceil(padLength / char.length)).substring(0, padLength);
return position === "left" ? padding + str : str + padding;
}
// 字符串截断
static truncate(str, length, suffix = "...") {
str = String(str);
if (str.length <= length) return str;
return str.substring(0, length - suffix.length) + suffix;
}
// 单词计数
static wordCount(str) {
return str.trim().split(/\s+/).filter(word => word.length > 0).length;
}
}
// 使用示例
console.log(StringOperations.concat("Hello", " ", "World")); // "Hello World"
console.log(StringOperations.repeat("*", 5)); // "*****"
console.log(StringOperations.pad("5", 3, "0")); // "005"
console.log(StringOperations.truncate("这是一个很长的字符串", 10)); // "这是一个很..."
console.log(StringOperations.wordCount("Hello world JavaScript")); // 33. 逻辑运算工具
javascript
class LogicOperations {
// 安全的逻辑与
static and(...values) {
for (let value of values) {
if (!value) return value;
}
return values[values.length - 1];
}
// 安全的逻辑或
static or(...values) {
for (let value of values) {
if (value) return value;
}
return values[values.length - 1];
}
// 条件选择
static select(condition, trueValue, falseValue) {
return condition ? trueValue : falseValue;
}
// 多条件检查
static all(...conditions) {
return conditions.every(condition => condition);
}
static any(...conditions) {
return conditions.some(condition => condition);
}
// 反转条件
static not(condition) {
return !condition;
}
}
// 使用示例
console.log(LogicOperations.and(true, true, false)); // false
console.log(LogicOperations.or(false, false, true)); // true
console.log(LogicOperations.select(5 > 3, "大于", "小于")); // "大于"
console.log(LogicOperations.all(5 > 3, 10 > 5, "hello")); // true
console.log(LogicOperations.any(5 > 10, 10 > 5, "")); // true运算符优先级表
以下是 JavaScript 运算符的优先级(从高到低):
- 分组:
() - 成员访问:
. [] - new(带参数列表):
new - 函数调用:
() - 可选链:
?. - new(无参数列表):
new - 后置递增/递减:
++ -- - 前置递增/递减:
++ -- - 一元加法/减法:
+ - - 按位非:
~ - 逻辑非:
! - typeof:
typeof - void:
void - delete:
delete - 幂运算:
** - 乘法/除法/取模:
* / % - 加法/减法:
+ - - 位移:
<< >> >>> - 关系运算符:
< <= > >= in instanceof - 相等运算符:
== != === !== - 按位与:
& - 按位异或:
^ - 按位或:
| - 逻辑与:
&& - 逻辑或:
|| - 空值合并:
?? - 条件运算符:
?: - 赋值运算符:
= += -= *= /= %= **= <<= >>= &= ^= |= ??= &&= ||= - 逗号运算符:
,
总结
JavaScript 运算符的核心要点:
- 算术运算符:+、-、*、/、%、**、++、--
- 赋值运算符:=、+=、-=、*=、/=、%=、**= 等
- 比较运算符:==、===、!=、!==、>、<、>=、<=
- 逻辑运算符:&&、||、!、??、&&=、||=、??=
- 位运算符:&、|、^、~、<<、>>、>>>
- 字符串运算符:+、+=(连接)
- 条件运算符:? :(三元运算符)
- 一元运算符:delete、typeof、void、in、instanceof
- 逗号运算符:,
- 运算符优先级:决定表达式计算顺序
- 类型转换:运算符涉及的隐式和显式转换
- 最佳实践:使用严格相等、合理使用短路求值、注意优先级
掌握运算符是编写高效、正确 JavaScript 代码的基础。在下一章节中,我们将学习 JavaScript 的正则表达式。