Skip to content

JavaScript 运算符

运算符是 JavaScript 中执行特定数学、逻辑或赋值操作的符号。理解各种运算符的用法和优先级对于编写正确的 JavaScript 代码至关重要。在本章节中,我们将深入学习 JavaScript 中的各种运算符及其使用方法。

什么是运算符

运算符是用于执行特定操作的符号,它们可以对一个或多个操作数进行操作。操作数可以是变量、常量或表达式。

javascript
let x = 5 + 3;  // + 是运算符,5 和 3 是操作数
let y = x * 2;  // * 是运算符,x 和 2 是操作数

运算符的分类

JavaScript 中的运算符可以按照不同的标准进行分类:

按操作数数量分类

  1. 一元运算符:只需要一个操作数
  2. 二元运算符:需要两个操作数
  3. 三元运算符:需要三个操作数

按功能分类

  1. 算术运算符
  2. 赋值运算符
  3. 比较运算符
  4. 逻辑运算符
  5. 位运算符
  6. 字符串运算符
  7. 条件(三元)运算符
  8. 逗号运算符
  9. 一元运算符
  10. 关系运算符

算术运算符

算术运算符用于执行基本的数学运算。

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.45

2. 字符串处理工具

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")); // 3

3. 逻辑运算工具

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 运算符的优先级(从高到低):

  1. 分组()
  2. 成员访问. []
  3. new(带参数列表):new
  4. 函数调用()
  5. 可选链?.
  6. new(无参数列表):new
  7. 后置递增/递减++ --
  8. 前置递增/递减++ --
  9. 一元加法/减法+ -
  10. 按位非~
  11. 逻辑非!
  12. typeoftypeof
  13. voidvoid
  14. deletedelete
  15. 幂运算**
  16. 乘法/除法/取模* / %
  17. 加法/减法+ -
  18. 位移<< >> >>>
  19. 关系运算符< <= > >= in instanceof
  20. 相等运算符== != === !==
  21. 按位与&
  22. 按位异或^
  23. 按位或|
  24. 逻辑与&&
  25. 逻辑或||
  26. 空值合并??
  27. 条件运算符?:
  28. 赋值运算符= += -= *= /= %= **= <<= >>= &= ^= |= ??= &&= ||=
  29. 逗号运算符,

总结

JavaScript 运算符的核心要点:

  1. 算术运算符:+、-、*、/、%、**、++、--
  2. 赋值运算符:=、+=、-=、*=、/=、%=、**= 等
  3. 比较运算符:==、===、!=、!==、>、<、>=、<=
  4. 逻辑运算符:&&、||、!、??、&&=、||=、??=
  5. 位运算符:&、|、^、~、<<、>>、>>>
  6. 字符串运算符:+、+=(连接)
  7. 条件运算符:? :(三元运算符)
  8. 一元运算符:delete、typeof、void、in、instanceof
  9. 逗号运算符:,
  10. 运算符优先级:决定表达式计算顺序
  11. 类型转换:运算符涉及的隐式和显式转换
  12. 最佳实践:使用严格相等、合理使用短路求值、注意优先级

掌握运算符是编写高效、正确 JavaScript 代码的基础。在下一章节中,我们将学习 JavaScript 的正则表达式。

本站内容仅供学习和研究使用。