1. 操作符概述

操作符是JavaScript中用于执行特定运算的符号或关键字。它们是编程语言的基础构建块,用于操作数据、执行计算、比较值和控制程序流程。

操作符的分类

  • 一元操作符:只需要一个操作数
  • 二元操作符:需要两个操作数
  • 三元操作符:需要三个操作数(只有条件操作符)

2. 算术操作符

算术操作符用于执行数学运算。

基本算术操作符

操作符名称示例结果
+加法5 + 38
-减法5 - 32
*乘法5 * 315
/除法6 / 32
%取余7 % 31
**幂运算2 ** 38

示例代码

// 基本算术运算
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.333...
console.log(a % b);  // 1
console.log(a ** b); // 1000
 
// 注意:字符串的加法运算
console.log("Hello" + " World"); // "Hello World"
console.log("5" + 3);            // "53" (字符串连接)
console.log(5 + "3");            // "53" (字符串连接)

3. 赋值操作符

赋值操作符用于给变量赋值。

基本赋值操作符

  • =:基本赋值

复合赋值操作符

操作符等价于示例结果
+=a = a + ba += 3将3加到a上
-=a = a - ba -= 3从a中减去3
*=a = a * ba *= 3将a乘以3
/=a = a / ba /= 3将a除以3
%=a = a % ba %= 3a对3取余
**=a = a ** ba **= 3a的3次方

示例代码

let x = 10;
 
x += 5;  // x = x + 5, 结果: 15
x -= 3;  // x = x - 3, 结果: 12
x *= 2;  // x = x * 2, 结果: 24
x /= 4;  // x = x / 4, 结果: 6
x %= 4;  // x = x % 4, 结果: 2
x **= 3; // x = x ** 3, 结果: 8
 
console.log(x); // 8

4. 自增/自减操作符

用于将数值增加或减少1。

前置和后置的区别

操作符名称说明
++a前置自增先增加,再返回值
a++后置自增先返回值,再增加
--a前置自减先减少,再返回值
a--后置自减先返回值,再减少

示例代码

let a = 5;
let b = 5;
 
// 前置自增
console.log(++a); // 6 (先增加,再返回)
console.log(a);   // 6
 
// 后置自增
console.log(b++); // 5 (先返回,再增加)
console.log(b);   // 6
 
// 在表达式中的使用
let x = 10;
let y = ++x + x++;
// ++x: x变为11,返回11
// x++: 返回11,然后x变为12
// y = 11 + 11 = 22
console.log(y); // 22
console.log(x); // 12

5. 比较操作符

比较操作符用于比较两个值,返回布尔值。

相等性比较

操作符名称说明
==相等值相等(会进行类型转换)
!=不等值不等(会进行类型转换)
===严格相等值和类型都相等
!==严格不等值或类型不等

关系比较

操作符名称示例
>大于5 > 3
<小于3 < 5
>=大于等于5 >= 5
<=小于等于3 <= 5

示例代码

// 相等性比较
console.log(5 == "5");   // true (类型转换)
console.log(5 === "5");  // false (严格比较)
console.log(5 != "5");   // false
console.log(5 !== "5");  // true
 
// 特殊值比较
console.log(null == undefined);  // true
console.log(null === undefined); // false
 
// 关系比较
console.log(5 > 3);   // true
console.log("abc" < "def"); // true (字符串比较)
 
// 注意:NaN的特殊性
console.log(NaN === NaN); // false
console.log(isNaN(NaN));  // true (正确检测NaN的方法)

6. 逻辑操作符

逻辑操作符用于布尔逻辑运算。

基本逻辑操作符

操作符名称说明
&&逻辑与所有操作数为真时返回真
|逻辑或任一操作数为真时返回真
!逻辑非对操作数取反

短路求值

  • &&:如果第一个操作数为假,不会评估第二个操作数
  • ||:如果第一个操作数为真,不会评估第二个操作数

示例代码

// 基本逻辑运算
console.log(true && true);   // true
console.log(true && false);  // false
console.log(false || true);  // true
console.log(!true);          // false
 
// 短路求值
let x = 5;
let y = 0;
 
// && 短路求值
console.log(x > 0 && ++y); // true, y变为1
console.log(x < 0 && ++y); // false, y不会增加
 
// || 短路求值
let name = "";
let defaultName = "Guest";
let displayName = name || defaultName; // "Guest"
 
// 实用模式
function greet(name) {
    name = name || "Guest"; // 默认值模式
    console.log("Hello, " + name);
}
 
// 用于条件执行
let isLoggedIn = true;
isLoggedIn && console.log("Welcome back!"); // 只有登录时才执行

7. 位操作符

位操作符直接操作数字的二进制表示。

位操作符列表

操作符名称示例说明
&按位与5 & 3对应位都为1则为1
|按位或5 | 3对应位有1则为1
^按位异或5 ^ 3对应位不同则为1
~按位取反~5所有位取反
<<左移5 << 1向左移动指定位数
>>右移5 >> 1向右移动指定位数
>>>无符号右移5 >>> 1无符号向右移动

示例代码

// 位运算示例
console.log(5 & 3);  // 1 (101 & 011 = 001)
console.log(5 | 3);  // 7 (101 | 011 = 111)
console.log(5 ^ 3);  // 6 (101 ^ 011 = 110)
console.log(~5);     // -6 (按位取反)
 
// 位移运算
console.log(5 << 1); // 10 (左移1位,相当于乘以2)
console.log(5 >> 1); // 2  (右移1位,相当于除以2)
 
// 实用技巧
// 检查奇偶数
function isOdd(num) {
    return (num & 1) === 1;
}
 
// 快速乘除2的幂
let num = 16;
console.log(num << 2); // 64 (乘以4)
console.log(num >> 2); // 4  (除以4)

8. 条件操作符(三元操作符)

条件操作符是JavaScript中唯一的三元操作符。

语法

condition ? value1 : value2

示例代码

// 基本用法
let age = 18;
let status = age >= 18 ? "成年" : "未成年";
console.log(status); // "成年"
 
// 嵌套三元操作符
let score = 85;
let grade = score >= 90 ? "A" : 
            score >= 80 ? "B" : 
            score >= 70 ? "C" : 
            score >= 60 ? "D" : "F";
console.log(grade); // "B"
 
// 在函数中使用
function max(a, b) {
    return a > b ? a : b;
}
 
// 用于默认值(ES6之前的方法)
function greet(name) {
    name = name ? name : "Guest";
    console.log("Hello, " + name);
}

9. typeof操作符

typeof操作符返回一个字符串,表示操作数的数据类型。

返回值列表

数据类型typeof返回值
undefined”undefined”
Boolean”boolean”
Number”number”
String”string”
Function”function”
Object”object”
Symbol”symbol”
BigInt”bigint”

示例代码

// 基本类型检测
console.log(typeof undefined); // "undefined"
console.log(typeof true);      // "boolean"
console.log(typeof 123);       // "number"
console.log(typeof "hello");   // "string"
console.log(typeof Symbol());  // "symbol"
 
// 特殊情况
console.log(typeof null);      // "object" (历史遗留问题)
console.log(typeof [1, 2, 3]); // "object"
console.log(typeof {});        // "object"
console.log(typeof function(){}); // "function"
 
// 实用函数
function getType(value) {
    if (value === null) return "null";
    if (Array.isArray(value)) return "array";
    return typeof value;
}
 
console.log(getType(null));    // "null"
console.log(getType([1, 2]));  // "array"
console.log(getType({}));      // "object"

10. in操作符

in操作符用于检查对象是否具有指定的属性。

语法

property in object

示例代码

// 对象属性检查
let person = {
    name: "John",
    age: 30
};
 
console.log("name" in person);    // true
console.log("height" in person);  // false
console.log("toString" in person); // true (继承的属性)
 
// 数组索引检查
let arr = ["a", "b", "c"];
console.log(0 in arr);  // true
console.log(3 in arr);  // false
 
// 与hasOwnProperty的区别
console.log(person.hasOwnProperty("name"));     // true
console.log(person.hasOwnProperty("toString")); // false
console.log("toString" in person);              // true
 
// 用于检查方法是否存在
if ("push" in Array.prototype) {
    console.log("数组支持push方法");
}

11. instanceof操作符

instanceof操作符用于检测构造函数的prototype属性是否出现在对象的原型链中。

语法

object instanceof constructor

示例代码

// 基本类型检测
let arr = [1, 2, 3];
let obj = {};
let date = new Date();
 
console.log(arr instanceof Array);   // true
console.log(arr instanceof Object);  // true (Array继承自Object)
console.log(obj instanceof Object);  // true
console.log(date instanceof Date);   // true
console.log(date instanceof Object); // true
 
// 自定义构造函数
function Person(name) {
    this.name = name;
}
 
let john = new Person("John");
console.log(john instanceof Person); // true
console.log(john instanceof Object); // true
 
// 注意:原始类型
console.log("hello" instanceof String); // false
console.log(123 instanceof Number);     // false
 
// 但是包装对象会返回true
console.log(new String("hello") instanceof String); // true
console.log(new Number(123) instanceof Number);     // true
 
// 用于类型检查函数
function isArray(value) {
    return value instanceof Array;
}
 
// ES6替代方案
console.log(Array.isArray(arr)); // true (推荐使用)

12. 解构赋值操作符

ES6引入的解构赋值允许从数组或对象中提取值。

数组解构

// 基本数组解构
let [a, b, c] = [1, 2, 3];
console.log(a, b, c); // 1 2 3
 
// 跳过元素
let [first, , third] = [1, 2, 3];
console.log(first, third); // 1 3
 
// 默认值
let [x = 10, y = 20] = [1];
console.log(x, y); // 1 20
 
// 剩余元素
let [head, ...tail] = [1, 2, 3, 4];
console.log(head);  // 1
console.log(tail);  // [2, 3, 4]
 
// 交换变量
let p = 1, q = 2;
[p, q] = [q, p];
console.log(p, q); // 2 1

对象解构

// 基本对象解构
let {name, age} = {name: "John", age: 30, city: "New York"};
console.log(name, age); // "John" 30
 
// 重命名
let {name: userName, age: userAge} = {name: "John", age: 30};
console.log(userName, userAge); // "John" 30
 
// 默认值
let {x = 10, y = 20} = {x: 1};
console.log(x, y); // 1 20
 
// 嵌套解构
let user = {
    id: 1,
    profile: {
        name: "John",
        email: "john@example.com"
    }
};
 
let {profile: {name: userName2, email}} = user;
console.log(userName2, email); // "John" "john@example.com"
 
// 函数参数解构
function greet({name, age = 25}) {
    console.log(`Hello ${name}, you are ${age} years old`);
}
 
greet({name: "Alice", age: 30}); // "Hello Alice, you are 30 years old"

13. 展开操作符

ES6的展开操作符(…)可以展开可迭代对象。

示例代码

// 数组展开
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
 
// 复制数组
let original = [1, 2, 3];
let copy = [...original];
copy.push(4);
console.log(original); // [1, 2, 3]
console.log(copy);     // [1, 2, 3, 4]
 
// 对象展开
let obj1 = {a: 1, b: 2};
let obj2 = {c: 3, d: 4};
let merged = {...obj1, ...obj2};
console.log(merged); // {a: 1, b: 2, c: 3, d: 4}
 
// 函数调用
function sum(a, b, c) {
    return a + b + c;
}
 
let numbers = [1, 2, 3];
console.log(sum(...numbers)); // 6
 
// 字符串展开
let str = "hello";
let chars = [...str];
console.log(chars); // ["h", "e", "l", "l", "o"]

14. 操作符优先级

了解操作符优先级有助于理解复杂表达式的求值顺序。

优先级表(从高到低)

优先级操作符说明
20()分组
19. []成员访问
18new构造函数调用
17()函数调用
16++ --后置递增递减
15! ~ + - ++ --一元操作符
14**幂运算
13* / %乘法类
12+ -加法类
11<< >> >>>位移
10< <= > >=关系比较
9== != === !==相等比较
8-4& ^ |位运算
3&&逻辑与
2|逻辑或
1?:条件操作符
0= += -=赋值

示例代码

// 优先级示例
let result1 = 2 + 3 * 4;    // 14 (先乘法,后加法)
let result2 = (2 + 3) * 4;  // 20 (括号优先)
 
// 复杂表达式
let a = 5;
let b = 3;
let c = 2;
let result = a + b * c > 10 && a < b || c == 2;
// 求值顺序:
// 1. b * c = 6
// 2. a + 6 = 11
// 3. 11 > 10 = true
// 4. a < b = false
// 5. true && false = false
// 6. c == 2 = true
// 7. false || true = true
console.log(result); // true
 
// 建议:使用括号明确意图
let clearResult = (a + (b * c) > 10) && (a < b) || (c == 2);

15. 常见陷阱和最佳实践

常见陷阱

  1. 类型转换陷阱
// 避免使用 == ,推荐使用 ===
console.log(0 == false);     // true
console.log("" == false);    // true
console.log(null == undefined); // true
 
// 推荐做法
console.log(0 === false);    // false
console.log("" === false);   // false
console.log(null === undefined); // false
  1. 浮点数运算
// 浮点数精度问题
console.log(0.1 + 0.2);      // 0.30000000000000004
console.log(0.1 + 0.2 === 0.3); // false
 
// 解决方案
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // true
  1. 自增操作符陷阱
let i = 1;
let arr = [i++, ++i, i++];
console.log(arr); // [1, 3, 3]
console.log(i);   // 4

最佳实践

  1. 使用严格比较
// 好的做法
if (value === null) { /* ... */ }
if (typeof value === "string") { /* ... */ }
 
// 避免
if (value == null) { /* ... */ }
  1. 合理使用逻辑操作符
// 使用 || 提供默认值
function greet(name) {
    name = name || "Guest";
    console.log("Hello, " + name);
}
 
// ES6+ 使用默认参数(更好)
function greetES6(name = "Guest") {
    console.log("Hello, " + name);
}
  1. 避免过度使用三元操作符
// 可以接受
let message = isLoggedIn ? "Welcome" : "Please login";
 
// 过于复杂,建议使用 if-else
let status = score >= 90 ? "A" : 
             score >= 80 ? "B" : 
             score >= 70 ? "C" : "F";
 
// 更好的做法
function getGrade(score) {
    if (score >= 90) return "A";
    if (score >= 80) return "B";
    if (score >= 70) return "C";
    return "F";
}

总结

JavaScript操作符是编程的基础工具,掌握它们的用法和特性对编写高质量的代码至关重要。记住以下要点:

  1. 类型安全:优先使用严格比较(=、!
  2. 可读性:使用括号明确运算优先级
  3. 性能:理解短路求值的特性
  4. 现代化:善用ES6+的新特性(解构、展开操作符)
  5. 避免陷阱:注意类型转换和浮点数运算的问题

下一篇: 各种语句