Appearance
运算符
运算符用于执行各种操作,如算术运算、比较、逻辑判断等。本章将详细介绍 JavaScript 中的各类运算符。
算术运算符
算术运算符用于执行数学计算。
基本算术运算符
javascript
// 加法运算符 (+)
let sum = 10 + 5; // 15
let concat = 'Hello ' + 'World'; // 'Hello World'(字符串拼接)
let numStr = 10 + '5'; // '105'(数字与字符串拼接)
// 减法运算符 (-)
let diff = 10 - 5; // 5
let negNum = 10 - '5'; // 5(字符串转换为数字)
// 乘法运算符 (*)
let product = 10 * 5; // 50
let repeat = 'ab' * 3; // NaN(字符串不能相乘)
// 除法运算符 (/)
let quotient = 10 / 5; // 2
let division = 10 / 3; // 3.333...
let divByZero = 10 / 0; // Infinity
// 取余运算符 (%)
let remainder = 10 % 3; // 1(10 除以 3 余 1)
let negRemainder = -10 % 3; // -1(结果符号与被除数相同)
let posRemainder = 10 % -3; // 1
// 幂运算符 (**) - ES2016
let power = 2 ** 3; // 8(2 的 3 次方)
let sqrt = 16 ** 0.5; // 4(16 的平方根)
// 幂运算等价于 Math.pow()
console.log(Math.pow(2, 3)); // 8一元运算符
javascript
// 一元加号 (+)
let str = '123';
console.log(+str); // 123(转换为数字)
console.log(+'abc'); // NaN
console.log(+true); // 1
console.log(+false); // 0
// 一元减号 (-)
console.log(-str); // -123
console.log(-(-123)); // 123
// 递增运算符 (++)
let a = 5;
console.log(a++); // 5(先返回,后递增)
console.log(a); // 6
let b = 5;
console.log(++b); // 6(先递增,后返回)
console.log(b); // 6
// 递减运算符 (--)
let c = 5;
console.log(c--); // 5(先返回,后递减)
console.log(c); // 4
let d = 5;
console.log(--d); // 4(先递减,后返回)
console.log(d); // 4
// 实际应用
let count = 0;
count++; // count 变为 1
count--; // count 变为 0字符串拼接
javascript
// 加号用于字符串拼接
let firstName = '张';
let lastName = '三';
let fullName = firstName + lastName; // '张三'
// 数字与字符串拼接
let age = 25;
let message = '年龄:' + age; // '年龄:25'
// 连续拼接
let result = '结果是:' + 10 + 20; // '结果是:1020'(从左到右拼接)
let result2 = 10 + 20 + '是结果'; // '30是结果'(先计算数字)
// 使用括号改变优先级
let result3 = '结果是:' + (10 + 20); // '结果是:30'
// 模板字符串(推荐)
let name = '张三';
let greeting = `你好,${name}!`; // '你好,张三!'赋值运算符
基本赋值运算符
javascript
// 简单赋值 (=)
let x = 10;
// 链式赋值
let a, b, c;
a = b = c = 10; // a, b, c 都等于 10
// 复合赋值运算符
let num = 10;
// 加法赋值 (+=)
num += 5; // 等价于 num = num + 5; 结果:15
// 减法赋值 (-=)
num -= 3; // 等价于 num = num - 3; 结果:12
// 乘法赋值 (*=)
num *= 2; // 等价于 num = num * 2; 结果:24
// 除法赋值 (/=)
num /= 4; // 等价于 num = num / 4; 结果:6
// 取余赋值 (%=)
num %= 4; // 等价于 num = num % 4; 结果:2
// 幂赋值 (**=) - ES2016
num **= 3; // 等价于 num = num ** 3; 结果:8
// 字符串拼接赋值
let str = 'Hello';
str += ' World'; // 'Hello World'解构赋值(ES6)
javascript
// 数组解构
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, y, z = 10] = [1, 2];
console.log(x, y, z); // 1 2 10
// 剩余元素
let [head, ...tail] = [1, 2, 3, 4, 5];
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
// 对象解构
let person = { name: '张三', age: 25 };
let { name, age } = person;
console.log(name, age); // 张三 25
// 重命名变量
let { name: userName, age: userAge } = person;
console.log(userName, userAge); // 张三 25
// 默认值
let { name, city = '北京' } = person;
console.log(city); // 北京
// 嵌套解构
let user = {
id: 1,
info: {
name: '张三',
address: {
city: '北京'
}
}
};
let { info: { name, address: { city } } } = user;
console.log(name, city); // 张三 北京比较运算符
比较运算符用于比较两个值,返回布尔值。
相等比较
javascript
// 相等 (==):宽松相等,会进行类型转换
console.log(5 == 5); // true
console.log(5 == '5'); // true(字符串转换为数字)
console.log(0 == ''); // true
console.log(0 == false); // true
console.log(null == undefined); // true
// 不相等 (!=)
console.log(5 != 3); // true
console.log(5 != '5'); // false
// 严格相等 (===):不会进行类型转换
console.log(5 === 5); // true
console.log(5 === '5'); // false(类型不同)
console.log(0 === ''); // false
console.log(0 === false); // false
console.log(null === undefined); // false
// 严格不相等 (!==)
console.log(5 !== '5'); // true
console.log(5 !== 5); // false
// 推荐使用严格相等 ===
// 避免类型转换带来的意外结果
// 对象比较(比较引用地址)
let obj1 = { name: '张三' };
let obj2 = { name: '张三' };
let obj3 = obj1;
console.log(obj1 == obj2); // false(不同对象)
console.log(obj1 === obj2); // false
console.log(obj1 === obj3); // true(同一引用)
// 数组比较
let arr1 = [1, 2, 3];
let arr2 = [1, 2, 3];
console.log(arr1 == arr2); // false
console.log(arr1 === arr2); // false大小比较
javascript
// 大于 (>)
console.log(10 > 5); // true
console.log(10 > 10); // false
console.log('b' > 'a'); // true(字符串按字典序比较)
// 小于 (<)
console.log(5 < 10); // true
console.log('a' < 'b'); // true
// 大于等于 (>=)
console.log(10 >= 10); // true
console.log(10 >= 5); // true
// 小于等于 (<=)
console.log(5 <= 5); // true
console.log(5 <= 10); // true
// 字符串比较
console.log('abc' < 'abd'); // true
console.log('abc' < 'abcd'); // true(短字符串较小)
console.log('ABC' < 'abc'); // true(大写字母 ASCII 码更小)
// 不同类型比较(会进行类型转换)
console.log('10' > 5); // true('10' 转换为 10)
console.log('abc' > 5); // false('abc' 转换为 NaN)
// 特殊情况
console.log(null > 0); // false
console.log(null == 0); // false
console.log(null >= 0); // true(null 转换为 0)
console.log(undefined > 0); // false
console.log(undefined < 0); // false逻辑运算符
逻辑运算符用于布尔值的逻辑运算。
基本逻辑运算
javascript
// 逻辑与 (&&):两个操作数都为 true 时返回 true
console.log(true && true); // true
console.log(true && false); // false
console.log(false && true); // false
console.log(false && false); // false
// 逻辑或 (||):至少一个操作数为 true 时返回 true
console.log(true || true); // true
console.log(true || false); // true
console.log(false || true); // true
console.log(false || false); // false
// 逻辑非 (!):取反
console.log(!true); // false
console.log(!false); // true
console.log(!!true); // true(双重否定,转换为布尔值)
// 优先级:! > && > ||
console.log(true || false && false); // true(&& 先执行)
console.log((true || false) && false); // false短路求值
javascript
// && 短路:第一个为 false 时,不计算第二个
let a = 0;
false && (a = 1);
console.log(a); // 0(赋值未执行)
// || 短路:第一个为 true 时,不计算第二个
let b = 0;
true || (b = 1);
console.log(b); // 0(赋值未执行)
// 利用短路设置默认值
let userName = '';
let displayName = userName || '匿名用户'; // '匿名用户'
let userAge = 0;
let displayAge = userAge || 18; // 18(注意:0 是假值)
// 使用 ?? 空值合并运算符(ES2020)
// 只在 null 或 undefined 时使用默认值
let age = 0;
let displayAge2 = age ?? 18; // 0(0 不是 null/undefined)
let value = null;
let result = value ?? '默认值'; // '默认值'
let value2 = undefined;
let result2 = value2 ?? '默认值'; // '默认值'逻辑运算返回值
javascript
// && 返回第一个假值或最后一个值
console.log(1 && 2); // 2
console.log(0 && 2); // 0
console.log(1 && 2 && 3); // 3
console.log(1 && 0 && 3); // 0
// || 返回第一个真值或最后一个值
console.log(1 || 2); // 1
console.log(0 || 2); // 2
console.log(0 || '' || 3); // 3
console.log(0 || '' || null); // null
// 实际应用
let user = {
name: '张三',
settings: {
theme: 'dark'
}
};
// 安全访问嵌套属性
let theme = user && user.settings && user.settings.theme; // 'dark'
// 可选链运算符 (?.) - ES2020
let theme2 = user?.settings?.theme; // 'dark'
let admin = null;
let adminTheme = admin?.settings?.theme; // undefined(不会报错)条件(三元)运算符
javascript
// 语法:条件 ? 表达式1 : 表达式2
// 条件为 true 返回表达式1,否则返回表达式2
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'
// 实际应用:显示不同内容
let isLoggedIn = true;
let welcomeMessage = isLoggedIn ? '欢迎回来!' : '请先登录';
console.log(welcomeMessage);
// 设置默认值
let userInput = '';
let displayName = userInput ? userInput : '匿名用户';
console.log(displayName); // '匿名用户'
// 条件渲染
let items = [];
let html = items.length > 0 ?
`<ul>${items.map(item => `<li>${item}</li>`).join('')}</ul>` :
'<p>暂无数据</p>';位运算符
位运算符将操作数视为 32 位二进制数进行运算。
基本位运算
javascript
// 按位与 (&):两位都为 1 时结果为 1
console.log(5 & 3); // 1
// 5: 0101
// 3: 0011
// &: 0001 = 1
// 按位或 (|):至少一位为 1 时结果为 1
console.log(5 | 3); // 7
// 5: 0101
// 3: 0011
// |: 0111 = 7
// 按位异或 (^):两位不同时结果为 1
console.log(5 ^ 3); // 6
// 5: 0101
// 3: 0011
// ^: 0110 = 6
// 按位非 (~):反转所有位
console.log(~5); // -6
// 5: 00000000000000000000000000000101
// ~5: 11111111111111111111111111111010 = -6(补码表示)
// 左移 (<<):所有位向左移动,低位补 0
console.log(5 << 1); // 10(5 * 2)
console.log(5 << 2); // 20(5 * 4)
// 右移 (>>):所有位向右移动,高位补符号位
console.log(10 >> 1); // 5(10 / 2)
console.log(-10 >> 1); // -5(保持符号)
// 无符号右移 (>>>):高位补 0
console.log(-10 >>> 1); // 2147483643(大正数)位运算应用
javascript
// 判断奇偶
function isOdd(n) {
return n & 1; // 奇数返回 1,偶数返回 0
}
console.log(isOdd(5)); // 1(奇数)
console.log(isOdd(4)); // 0(偶数)
// 取整(向下取整)
console.log(~~3.7); // 3
console.log(3.7 | 0); // 3
// 交换两个数(不使用临时变量)
let a = 5, b = 3;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(a, b); // 3 5
// 权限判断(位掩码)
const READ = 1; // 0001
const WRITE = 2; // 0010
const EXECUTE = 4; // 0100
let permission = READ | WRITE; // 0011
// 检查权限
console.log(permission & READ); // 1(有读权限)
console.log(permission & EXECUTE); // 0(无执行权限)
// 添加权限
permission |= EXECUTE;
// 移除权限
permission &= ~WRITE;其他运算符
typeof 运算符
javascript
// typeof 返回数据类型的字符串
console.log(typeof 42); // 'number'
console.log(typeof 'hello'); // 'string'
console.log(typeof true); // 'boolean'
console.log(typeof undefined); // 'undefined'
console.log(typeof null); // 'object'
console.log(typeof {}); // 'object'
console.log(typeof []); // 'object'
console.log(typeof function(){}); // 'function'
// typeof 的括号可选
console.log(typeof 42); // 'number'
console.log(typeof(42)); // 'number'
// 检测未声明的变量
console.log(typeof undeclaredVar); // 'undefined'(不会报错)instanceof 运算符
javascript
// instanceof 检测对象是否是某个构造函数的实例
console.log([] instanceof Array); // true
console.log([] instanceof Object); // true
console.log({} instanceof Object); // true
console.log(new Date() instanceof Date); // true
// 自定义构造函数
function Person(name) {
this.name = name;
}
let person = new Person('张三');
console.log(person instanceof Person); // true
console.log(person instanceof Object); // truein 运算符
javascript
// in 检查属性是否存在于对象中
let person = { name: '张三', age: 25 };
console.log('name' in person); // true
console.log('city' in person); // false
// 检查继承的属性
console.log('toString' in person); // true(继承自 Object)
// 检查数组索引
let arr = ['a', 'b', 'c'];
console.log(0 in arr); // true
console.log(3 in arr); // falsedelete 运算符
javascript
// delete 删除对象属性
let person = { name: '张三', age: 25 };
console.log(delete person.age); // true(删除成功)
console.log(person); // { name: '张三' }
// 删除不存在的属性返回 true
console.log(delete person.city); // true
// 不能删除 var 声明的变量
var x = 10;
console.log(delete x); // false
console.log(x); // 10
// 不能删除内置属性
console.log(delete Math.PI); // false
// 删除数组元素
let arr = [1, 2, 3];
delete arr[1];
console.log(arr); // [1, empty, 3]
console.log(arr.length); // 3(长度不变)逗号运算符
javascript
// 逗号运算符执行多个表达式,返回最后一个表达式的值
let x = (1, 2, 3);
console.log(x); // 3
// 在 for 循环中使用
for (let i = 0, j = 10; i < j; i++, j--) {
console.log(i, j);
}
// 函数返回多个值
function getCoordinates() {
let x = 10, y = 20;
return (x++, y++, { x, y });
}
console.log(getCoordinates()); // { x: 11, y: 21 }void 运算符
javascript
// void 计算表达式但不返回值(返回 undefined)
console.log(void 0); // undefined
console.log(void(1 + 1)); // undefined
// 常用于阻止链接的默认行为
// <a href="javascript:void(0)" onclick="doSomething()">点击</a>
// 立即执行函数表达式(IIFE)
void function() {
console.log('执行了');
}();展开运算符(ES6)
javascript
// 展开数组
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let combined = [...arr1, ...arr2];
console.log(combined); // [1, 2, 3, 4, 5, 6]
// 复制数组
let copy = [...arr1];
console.log(copy); // [1, 2, 3]
// 展开对象
let obj1 = { a: 1, b: 2 };
let obj2 = { c: 3, ...obj1 };
console.log(obj2); // { c: 3, a: 1, b: 2 }
// 函数参数展开
function sum(a, b, c) {
return a + b + c;
}
let nums = [1, 2, 3];
console.log(sum(...nums)); // 6剩余运算符(ES6)
javascript
// 收集剩余参数
function sum(...args) {
return args.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3, 4, 5)); // 15
// 与普通参数结合
function greet(greeting, ...names) {
names.forEach(name => {
console.log(`${greeting}, ${name}!`);
});
}
greet('你好', '张三', '李四', '王五');
// 解构中的剩余元素
let [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]运算符优先级
javascript
// 运算符优先级从高到低(部分)
// 1. 括号 ()
// 2. 成员访问 . []
// 3. 函数调用 ()
// 4. new
// 5. 后置递增/递减 ++ --
// 6. 逻辑非 !、按位非 ~、一元运算符 + -、typeof、void、delete
// 7. 幂 **
// 8. 乘、除、取余 * / %
// 9. 加、减 + -
// 10. 位移 << >> >>>
// 11. 比较 < <= > >= in instanceof
// 12. 相等 == != === !==
// 13. 按位与 &
// 14. 按位异或 ^
// 15. 按位或 |
// 16. 逻辑与 &&
// 17. 逻辑或 ||
// 18. 空值合并 ??
// 19. 条件(三元) ?:
// 20. 赋值 = += -= *= /= 等
// 21. 展开 ...
// 22. 逗号 ,
// 示例
let result = 2 + 3 * 4; // 14(先乘后加)
let result2 = (2 + 3) * 4; // 20(括号优先)
let x = 5;
let y = x++ + ++x; // 5 + 7 = 12
// x++ 返回 5,x 变为 6
// ++x 返回 7,x 变为 7
// 使用括号明确优先级
let complex = ((a > b) && (c < d)) || (e === f);小结
本章学习了 JavaScript 的各种运算符:
- 算术运算符:+、-、*、/、%、**、++、--
- 赋值运算符:=、+=、-=、*=、/=、%=、**=
- 比较运算符:==、===、!=、!==、>、<、>=、<=
- 逻辑运算符:&&、||、!
- 条件运算符:? :
- 位运算符:&、|、^、~、<<、>>、>>>
- 其他运算符:typeof、instanceof、in、delete、逗号、展开、剩余
下一章我们将学习 流程控制,了解如何控制代码的执行流程。
