JS核心操作符:从基础到ES6+
ECMAScript操作符
- 一、一元操作符
- 1.递增、递减操作符(++/- -)
- 2.一元加和减(+/-)
- 二、位操作符
- 1.按位非(~)
- 2.按位与(&)
- 3.按位或(|)
- 4.按位异或(^)
- 5. 左移 (<<)
- 6. 有符号右移 (>>)
- 7. 无符号右移 (>>>)
- 三、布尔操作符
- 1. 逻辑非 (!)
- 2. 逻辑与 (&&)
- 3. 逻辑或 (||)
- 四、算术操作符
- 1. 加法操作符 (+)
- 2. 减法操作符 (-)
- 3. 乘法操作符 ( * )
- 4. 除法操作符 ( / )
- 5. 取模操作符 ( % )
- 五、关系操作符
- 特殊关系操作符( in )
- 特殊关系操作符( instanceof )
- 六、相等操作符
- 1. 等于和不等于(== / !=)
- 2. 全等和不全等(=== / !==)
- 七、其它操作符
- 1. 条件操作符(三元表达式)
- 2. 赋值操作符( = )
- 3. 逗号操作符(,)
- 八 、ES6+ 新增操作符
- 1. 指数操作符 (**)
- 2. 链判断运算符( ?. )
- 3. 空值合并操作符 (??)
- 4. 逻辑赋值操作符 (&&=, ||=, ??=)
- 5. 扩展运算符 (...)
- 最后
操作符包括数学操作符(加、减)、位操作符、关系操作符和相等操作符等。操作符也是独特的,因为可用于各种值,包括字符串、数值、布尔值、对象。在应用给对象时会调用 valueOf() 或 toString() 方法来取得可计算的值。
一、一元操作符
含义:只操作一个值的操作符,是ES中最简单的操作符。
1.递增、递减操作符(++/- -)
递增和递减操作符搬运自C语言,有两个版本:前缀版和后缀版,它们的主要区别在于返回值时机和变量值变化时机。
前缀版++a,递减一样(先递增/减,再返回新值 )
let a = 29;const result = ++a; // 先递增,再返回新值 console.log(result); // 30(返回递增后的值)console.log(a); // 30(变量已递增)
操作顺序:先执行 a = a + 1,然后返回新值
返回值:递增后的新值(30)
变量最终值:30
后缀版a++,递减一样(先返回新值,再递增/减 )
let a = 29;const result = a++; // 先返回当前值,再递增 console.log(result); // 29(返回递增前的值)console.log(a); // 30(变量已递增)
操作顺序:先返回当前值(29),然后执行 a = a + 1
返回值:递增前的原始值(29)
变量最终值:30
场景题:连续运算
let b = 10;const c = b-- + --b; // 分解:// 1. b-- 返回10(当前值),b变为9// 2. --b 先减1(b变为8),返回8// 结果:c = 10 + 8 = 18
- 对于字符串,如果是有效的数值形式,转化为数值再改变
- 对于字符串,如果不是有效的数值,则将变量设置为NaN
- 对于布尔值,false转换为0,true转换为1,再应用改变
- 对于对象,则调用valueOf()取得可以操作的值
2.一元加和减(+/-)
一元加和减跟在高数中的用途一样
一元加放在变量前面对数值没有影响
一元减放在变量前面,主要用于把数值变为负值
// 数字类型保持不变console.log(+10); // 10console.log(+3.14); // 3.14// 字符串转换为数字console.log(+"5"); // 5 (数字)console.log(+"3.14"); // 3.14console.log(+"0xFF"); // 255 (十六进制转换)// 布尔值转换console.log(+true); // 1console.log(+false); // 0// 特殊值处理console.log(+null); // 0console.log(+undefined); // NaNconsole.log(+""); // 0 (空字符串)
用途
// 字符串转数字
const num = +"42"; // 比parseInt()更快,但仅适用于纯数字字符串
// 日期转时间戳
const timestamp = +new Date();
- 字符串:尝试解析为数字(失败则返回NaN)
- 布尔值:true→1, false→0
- null→0
- undefined→NaN
- 对象类型转换: 调用对象的valueOf()方法
二、位操作符
位操作符是 JavaScript 中直接操作数值的底层二进制位的操作符。这些操作符将操作数视为 32 位整数(0 和 1 的序列),执行位级操作后返回标准的 JavaScript 数值。
1.按位非(~)
它的作用但是返回数值的唯一补数。
let num1 = 25 //二进制 11001
let num2 = ~num1 //二进制 00110
console.log(num2) // -26
这里按位非作用得到了数值25,得到结果的结果是 -26。由此可以看出,按位非的最终效果是对数值取反并减1,就像下面的操作一样
let num1 = 25
let num2 = -num1 - 1
console.log(num2) // -26
尽管两者结果返回一样, 但是按位非操作的速度快得多,因为它是在数值的底层表示上完成的。
2.按位与(&)
将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的操作。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 0 |
规则: 两位都为 1 时结果才为 1
5 & 3 → 1 // 分解:// 5 → 0101// 3 → 0011// & → 0001 → 1
应用场景: 检查奇偶性:num & 1 (1=奇数, 0=偶数)
3.按位或(|)
将两个数的每一个位对齐,然后基于真值表中的规则,对每一位执行相应的操作。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 1 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
规则:任一位为 1 时结果为 1
5 | 3 → 7// 分解:// 5 → 0101// 3 → 0011// | → 0111 → 7
应用场景:快速取整:3.14 | 0 → 3 (比Math.floor()更快)
4.按位异或(^)
同样有两个操作数,基于真值表中的规则,对每一位执行相应的操作。
第一个数值的位 | 第二个数值的位 | 结果 |
---|---|---|
1 | 1 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
0 | 0 | 0 |
规则:两位不同时结果为 1
5 ^ 3 → 6// 分解:// 5 → 0101// 3 → 0011// ^ → 0110 → 6
5. 左移 (<<)
规则:向左移动指定位数,右侧补 0
5 << 2 → 20// 分解:
// 5 → 0101
// << 2 → 010100 → 20
注意:左移会保留他所操作数值的符号,比如 -1左移五位,将得到 -64。
6. 有符号右移 (>>)
规则:向右移动指定位数,左侧补符号位(保留正负号)
let oldValue = 64 //等于二进制 1000000
let newValue = oldValue >> 5 //等于二进制 0000010 ,即十进制2
7. 无符号右移 (>>>)
规则:向右移动,左侧补 0
对于正数来说,跟有符号右移效果相同。
let oldValue = 64 //等于二进制 1000000
let newValue = oldValue >> 5 //等于二进制 0000010 ,即十进制2
对于负数,无符号右移将负数的二进制表示为正数的二进制来表示,因为负数是其绝对值的二补数,所以右移之后结果变得非常大
let oldValue = -64 //等于二进制 11111111111111111111111111000000
let newValue = oldValue >> 5 //等于十进制 134217726
三、布尔操作符
布尔操作符是 JavaScript 中用于逻辑判断和布尔值转换的核心操作符,主要包括逻辑非(!)、逻辑与(&&)和逻辑或(||)。这些操作符不仅用于布尔运算,还因其独特的短路特性在 JavaScript 编程中被广泛用于条件判断、默认值设置等场景。
1. 逻辑非 (!)
将操作数强制转换为布尔值后取反。
- 如果操作数是对象,则返回 false
- 如果操作数是空字符串,则返回 true
- 如果操作数是非空字符串,则返回 false
- 如果操作数是数值0,则返回 true
- 如果操作数是数值非0数值(包括Infinity),则返回 false
- 如果操作数是null,则返回 true
- 如果操作数是NaN,则返回 true
- 如果操作数是undefined,则返回 true
console.log(!{}); // false console.log(!""); // true console.log(!"hi"); // false console.log(!true); // falseconsole.log(!false); // trueconsole.log(!0); // true console.log(!1); // false console.log(!null); // trueconsole.log(!undefined); // true
也可以同时用两个感叹号(!!),相当于调用转型函数Bollen()。无论操作数是什么类型,第一个感叹号总会返回布尔值。第二个感叹号对该布尔值取反,从而给出变量真正对应的布尔值。
console.log(!!{}); // trueconsole.log(!!""); // false console.log(!!"hi"); // trueconsole.log(!!true); // trueconsole.log(!!false); // falseconsole.log(!!0); // falseconsole.log(!!1); // trueconsole.log(!!null); // falseconsole.log(!!undefined); // false
2. 逻辑与 (&&)
当且仅当所有操作数都为真时返回真
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | false |
false | true | false |
false | false | false |
逻辑与操作数可用于任何类型的操作数,不限于布尔值。如果有操作数不是布尔值,则逻辑与不一定会返回布尔值,而是遵循以下规则
- 如果第一个操作数是对象,则返回第二个操作数
- 如果第二个操作数是对象,则只有第一个操作数值为true才会返回该对象
- 如果两个操作数都是对象,则返回第二个操作数
- 如果有一个操作数是null,则返回null
- 如果有一个操作数是NaN,则返回NaN
- 如果有一个操作数是undefined,则返回undefined
console.log(Object && 1); // 1console.log(1 && Object); // Object console.log(1 && null); // null
逻辑与操作符是一种短路操作符,如果第一个操作数决定了结果,那么永远不会对第二个操作室求值。
**如果第一个操作数是false,**那么无论第二个操作数是什么值,结果都不会等于true。
例子:
let result = bool && somethingError
如果bool 值为 true,那么求值时会报错
如果bool 值为 false,那么逻辑与操作符不会对其求值,因此右边的操作数是没有意义的。
3. 逻辑或 (||)
当任一操作数为真时返回真
第一个操作数 | 第二个操作数 | 结果 |
---|---|---|
true | true | true |
true | false | true |
false | true | true |
false | false | false |
逻辑或与逻辑或类似,如果有操作数不是布尔值,则逻辑与不一定会返回布尔值,而是遵循以下规则
- 如果第一个操作数是对象,则返回第一个操作数
- 如果第一个操作数求值为false,则返回第二个操作数
- 如果两个操作数都是对象,则返回第一个操作数
- 如果两个操作数是null,则返回null
- 如果两个操作数是NaN,则返回NaN
- 如果两个操作数是undefined,则返回undefined
console.log(Object || 1); // Object console.log(0 || Object); // Object console.log(1 || null); // 1 console.log(null || null); // null
逻辑或与逻辑与类似,只不过是第一个值为true ,就不会执行后续的值了。
四、算术操作符
包含标准四则运算操作符(+, -, *, /, %),其行为遵循数学规则但有特殊边界处理。
1. 加法操作符 (+)
加法操作符用于求两个数的和,比如 let result = 1 + 2
如果两个操作符都是数值,遵循以下规则
- 如果有一任意操作符是NaN,则返回NaN
- 如果是Infinity 加 Infinity ,则返回 Infinity
- 如果是-Infinity 加 -Infinity ,则返回 -Infinity
- 如果是 Infinity 加 -Infinity ,则返回 NaN
- 如果是+0 加 +0 ,则返回 +0
- 如果是-0 加 +0 ,则返回 +0
- 如果是-0 加 -0 ,则返回 -0
如果有一个操作符是字符串,遵循一下规则
- 如果是两个字符串,则将第二个字符串拼接到第一个字符串后面
- 如果只有一个操作数是字符串,则将另一个操作数转换为字符串,再将两个字符串拼接。
- 如果有任一操作数是对象、数值或布尔值,则调用它们的 toString() 方法获取字符串
- 对于undefined 和 null,则调用String() 函数,分别获取"undefined" 和 “null”
5 + '5' // '55'5 + {} // '5[object Object]'5 + null // 5 (null → 0)'5' + null // '5null' (null → 'null')5 + undefined // NaN (undefined → NaN)
2. 减法操作符 (-)
与加法操作符一样,减法操作符也有一组规则用于处理ES中不同类型的转换
- 如果两个操作符都是数值,则执行数学减法运算并返回结果
- 如果有一任意操作符是NaN,则返回NaN
- 如果是Infinity 减 Infinity ,则返回 NaN
- 如果是-Infinity 减 -Infinity ,则返回 NaN
- 如果是 Infinity 减 -Infinity ,则返回 Infinity
- 如果是 -Infinity 减 Infinity ,则返回 -Infinity
- 如果是+0 减 +0 ,则返回 +0
- 如果是+0 减 -0 ,则返回 -0
- 如果是-0 减 -0 ,则返回 +0
- 如果任一操作数是字符串、布尔值、null、undefined,则先在后台使用number()将其转化为数值,再根据前面的规则执行数学运算。如果转换结果是NaN,则减法运算结果是NaN。
- 如果有任一操作符是对象,则调用 valueOf() 取得表示它的值。如果该值是NaN,则减法计算结果是NaN。如果对象没有valueOf() 方法,则调用其 toString()方法,然后再将其得到的字符串转换为数值。
5 - 3 // 2'5' - 3 // 2 ( '5' 转为 5 )5 - '3' // 2 ( '3' 转为 3 )'a' - 3 // NaN (无法转换为数字)NaN - 1 // NaN5 - null // 5 null被转换为0
3. 乘法操作符 ( * )
乘法操作符由一个星号( * )表示,可以用于两个数值的乘积
乘法操作符 遵循以下规则
- 如果两个操作符都是数值,则执行数学乘法运算并返回结果
- 如果有一任意操作符是NaN,则返回NaN
- 如果是Infinity 乘 0 ,则返回 NaN
- 如果是Infinity 乘 非0的有限值 ,则根据第二个操作数的符号返回 Infinity 和 -Infinity
- 如果是Infinity 乘 Infinity,则返回 Infinity
- 如果有不是数值的操作数,则先在后台用number()将其转换为数值,然后再执行上面的规则
2 * 3 // 6'2' * '3' // 6 (字符串转为数字)Infinity * 0 // NaN
4. 除法操作符 ( / )
除法操作符由一个斜杠( / )表示,可以用于计算第一个操作数除以第二个操作数的商
除法操作符 遵循以下规则
- 如果两个操作符都是数值,则执行数学除法运算并返回结果
- 如果有一任意操作符是NaN,则返回NaN
- 如果是Infinity 除 Infinity ,则返回 NaN
- 如果是0 除 0,则返回 NaN
- 如果是非0的有限值 除 0 ,则根据第一个操作数的符号返回 Infinity 和 -Infinity
- 如果是Infinity 除 任何数值,则根据第二个操作数的符号返回 Infinity 和 -Infinity
- 如果有不是数值的操作数,则先在后台用number()将其转换为数值,然后再执行上面的规则
6 / 3 // 2 '222' / 0 // Infinity0 / 0 // NaNtrue / 0.5 //2
5. 取模操作符 ( % )
取模(余数)操作符由一个百分比符号( % )表示,返回除法的余数
取模操作符 遵循以下规则
- 如果操作数是数值,则执行常规除法运算,返回余数
- 如果被除数是无限值,除数是有限值,则返回NaN
- 如果被除数是有限值,除数是0,则返回NaN
- 如果是Infinity 除 Infinity ,则返回 NaN
- 如果被除数是有限值,除数是无限值,则返回被除数
- 如果被除数是0,除数不是0,则返回0
- 如果有不是数值的操作数,则先在后台用number()将其转换为数值,然后再执行上面的规则
5 % 2 // 1-5 % 2 // -15.5 % 2 // 1.510 % 0 // NaN11 % Infinity // 11
五、关系操作符
关系操作符执行比较两个值的操作,包括小于( < )、大于( > )、小于等于( <= )、大于等于( >= ),它们返回布尔值(true或false)表示比较结果。
- 如果操作数都是数值,则执行数值比较
- 如果操作数都是字符串,则逐个比较字符串中对应字符的编码
- 如果有任一操作数是数值,则将另一个操作数转换为数值,执行数值比较
- 如果有任一操作数是对象,则调用valueOf()方法,取得结果后再根据前面的规则比较,如果没有valueOf(),则调用toString()方法。
- 如果任一操作数是布尔值,则将其转换为数值再执行比较
console.log('23' < '3'); // true '2'的编码是50,'3'的编码是51
console.log('10' > 5); // true (10 > 5) 字符串转为数字
console.log('a' > 5); // false 'a'会转换为NaN
// 布尔值参与比较(true→1, false→0)
console.log(true > false); // true (1 > 0)
console.log(false < 1); // true (0 < 1)
// null 和 undefined 特殊处理
console.log(null < 0); // false (null→0, 0<0? false)
console.log(null <= 0); // true (null→0, 0<=0? true)
console.log(undefined > 0); // false (undefined→NaN)console.log({} > 0); // false ({}→'[object Object]')
特殊关系操作符( in )
检查属性是否存在于对象或其原型链中
const car = { make: 'Toyota', year: 2020 };// 对象属性检查console.log('make' in car); // trueconsole.log('model' in car); // false// 数组索引检查const colors = ['red', 'green', 'blue'];console.log(0 in colors); // true (索引0存在)console.log(3 in colors); // false (索引3不存在)console.log('length' in colors);// true (继承属性)// 原型链属性console.log('toString' in car); // true (来自Object.prototype)
特殊关系操作符( instanceof )
检查对象是否是特定构造函数的实例
// 基础类型console.log('hello' instanceof String); // false (原始类型)console.log(new String('hello') instanceof String); // true// 内置对象const arr = [1, 2, 3];console.log(arr instanceof Array); // trueconsole.log(arr instanceof Object); // true (所有对象都是Object的实例)// 自定义类class Vehicle {}class Car extends Vehicle {}const myCar = new Car();console.log(myCar instanceof Car); // trueconsole.log(myCar instanceof Vehicle); // trueconsole.log(myCar instanceof Object); // true// 边界情况console.log(null instanceof Object); // falseconsole.log(undefined instanceof Object); // false
六、相等操作符
判断两个变量是否相等
1. 等于和不等于(== / !=)
等于用两个等于号表示( == ),如果相同则返回true。不等于用( != )表示,如果不相等则返回true。这两个操作符都会先进行强制转换在确定操作数是否相等。
规则
- 如果任一操作数是布尔值,则将其转换为数值再比较是否相等。false转换为0,true转换为1
- 如果一个操作数是字符串,另一个操作数是数值,则尝试将字符串转换为数值,再比较是否相等
- 如果一个操作数是对象,另一个不是,则调用对象的valueOf()方法取得其原始值,再根据前面的规则进行比较
- null与undefined相等
- null与undefined不能转换为其他类型的值进行比较
- 如果有任一操作数是NaN,则相等返回false,不相等返回true,NaN不等于NaN</.font>
- 如果两个操作数都是对象,则比较他们是不是同一个对象。如果两个操作数都指向同一个对象,则返回true,否则不相等
console.log(5 == '5'); // true (5 == 5)
console.log('' == 0); // true (0 == 0)
console.log(true == 1); // true (1 == 1)
console.log(false == 0); // true (0 == 0)
console.log(null == undefined); // true const obj = { toString: () => '5' };
console.log(obj == 5); // true ('5' == 5 → 5 == 5) console.log([] == 0); // true ([]→''→0)
console.log([] == ''); // true
console.log([] == []); // false (不同引用)
console.log(NaN == NaN); // false
放一张比较图
2. 全等和不全等(=== / !==)
全等和不全等操作符与上面类似,只不过它们在比较时不会转换操作数
console.log(5 === '5'); // false
console.log(true === 1); // false
console.log(5 === 5); // true
console.log(null === undefined); // false
注意:由于相等和不相等操作符存在类型转换问题,因此推荐使用全等和不全等操作符。这样有助于在代码中保持数据的完整性。
七、其它操作符
1. 条件操作符(三元表达式)
语法:variable = 条件 ? 表达式1 : 表达式2
上面代码执行了条件赋值操作,根据条件
的值决定将哪个值赋值给变量 variable。如果条件
值为true,则赋值表达式1
。如果为false则赋值表达式2
。
// 基本用法
const age = 20;
const status = age >= 18 ? '成年人' : '未成年人';
console.log(status); // "成年人"// 嵌套条件
const score = 85;
const grade = score >= 90 ? 'A' : score >= 80 ? 'B' : score >= 70 ? 'C' : 'D';
console.log(grade); // "B"// 函数返回值
function getFee(isMember) {return isMember ? '$2.00' : '$10.00';
}
console.log(getFee(true)); // "$2.00"
console.log(getFee(false)); // "$10.00"
2. 赋值操作符( = )
简单赋值用等于号( = ),表示将右边的值赋值给左边的变量
let x = 10; // 基本赋值
const y = x; // 值拷贝// 链式赋值(从右向左)
let a, b, c;
a = b = c = 5;
console.log(a, b, c); // 5, 5, 5
// 解构赋值
const [x, y] = [1, 2];
const { name, age } = user;
3. 逗号操作符(,)
逗号操作符可以用来在一条语句中执行多个操作 let num1 = 1,num2 = 2,num3 = 3
基本用法
let a = (1, 2, 3); // a = 3 a将被赋值表达式中最后一项
for循环中使用
for (let i = 0, j = 10; i < j; i++, j--) {console.log(i, j);
}
// 输出:0 10, 1 9, ..., 4 6
箭头函数返回值
const getData = () => (fetchData(), processResult());// 等价于:const getData = () => {fetchData();return processResult();};
八 、ES6+ 新增操作符
1. 指数操作符 (**)
Math.pow(3,2) === 3**2 //9
指数赋值操作符 **=
进行执行指数运算和结果的赋值操作
let num = 2num **= 3 // 等同于 num = num ** 3console.log(num) // 8let b = 4 b **= 3 // 等同于 b = b * b * b; 64
2. 链判断运算符( ?. )
如果读取对象内部的某个属性,往往需要判断一下,属性的上层对象是否存在。比如,读取message.body.user.firstName
这个属性,安全的写法是写成下面这样。
// 错误的写法const firstName = message.body.user.firstName || 'default';// 正确的写法const firstName = (message && message.body && message.body.user && message.body.user.firstName) || 'default';
上面例子中,firstName属性在对象的第四层,所以需要判断四次,每一层是否有值。
三元运算符?:也常用于判断对象是否存在。
这样的层层判断非常麻烦,因此 ES2020 引入了“链判断运算符”(optional chaining operator)?.
,简化上面的写法。
const firstName = message?.body?.user?.firstName || 'default';
上面代码使用了?.
运算符,直接在链式调用的时候判断,左侧的对象是否为null或undefined。如果是的,就不再往下运算,而是返回undefined。
a?.b // 等同于 a == null ? undefined : a.ba?.b() // 等同于 a == null ? undefined : a.b()
规则:
- 本质上,
?.
运算符相当于一种短路机制,只要不满足条件,就不再往下执行,直接返回undefined - 如果属性链有圆括号,链判断运算符对圆括号外部没有影响,只对圆括号内部有影响。
(a?.b).c // 等价于 (a == null ? undefined : a.b).c
- 右侧不得为十进制数值、
- 不能用于赋值
- 不能用于未声明的变量、构造函数、模板字符串等
3. 空值合并操作符 (??)
只有运算符左侧的值为null
或undefined
时,才会返回右侧的值。
console.log(null ?? "default"); // "default"console.log(undefined ?? "default"); // "default"console.log(0 ?? 100); // 0console.log("" ?? "default"); // ""console.log(false ?? true); // false
这个运算符的一个目的,就是跟链判断运算符?.
配合使用,为null
或undefined
的值设置默认值。
const value = obj.key?.value ?? 404;
上面代码中,如果obj.key
是null或undefined,或者 obj.key.value
是null或undefined,就会返回默认值404。也就是说,这一行代码包括了两级属性的判断。
这个运算符很适合判断函数参数是否赋值。
function Component(props) {const enable = props.enabled ?? true;// …}//等同于这种写法function Component(props) {const { enabled: enable = true} = props;// …}
注意:??
本质上是逻辑运算,它与其他两个逻辑运算符&&
和||
有一个优先级问题,它们之间的优先级到底孰高孰低。优先级的不同,往往会导致逻辑运算的结果不同。
现在的规则是,如果多个逻辑运算符一起使用,必须用括号表明优先级,否则会报错。
// 错误写法:语法错误a ?? b || c; // 正确写法:使用括号(a ?? b) || c;a ?? (b || c);
应用场景
// 1. 配置默认值const PORT = process.env.PORT ?? 3000;// 2. 函数参数默认值function connect(options = {}) {const timeout = options.timeout ?? 5000;const retries = options.retries ?? 3;}// 3. 结合解构使用const { width = 100, height = null } = element.getDimensions();const actualHeight = height ?? 200;
4. 逻辑赋值操作符 (&&=, ||=, ??=)
ES2021 引入,简化条件赋值操作
这三个运算符 ||=、&&=、??=
相当于先进行逻辑运算,然后根据运算结果,再视情况进行赋值运算。
// 逻辑或赋值 (||=)let x = 0;x ||= 10; // 等价于 x = x || 10console.log(x); // 10// 逻辑与赋值 (&&=)let y = 5;y &&= 10; // 等价于 y = y && 10console.log(y); // 10// 空值合并赋值 (??=)let z = null;z ??= 15; // 等价于 z = z ?? 15console.log(z); // 15
// 旧方式if (!obj.prop) {obj.prop = defaultValue;}// 新方式obj.prop ||= defaultValue;// 旧方式user.id = user.id || 1;// 新方式user.id ||= 1;
5. 扩展运算符 (…)
ES2015 (ES6) 引入,功能强大且应用广泛
// 1. 数组复制 (浅拷贝)const original = [1, 2, { a: 3 }];const copy = [...original]; copy[2].a = 4; // 影响原数组中的对象// 2. 数组合并const arr1 = [1, 2];const arr2 = [3, 4];const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]// 3. 数组去重const duplicates = [1, 2, 2, 3, 4, 4];const unique = [...new Set(duplicates)]; // [1, 2, 3, 4]// 4. 字符串转数组const str = "hello";const chars = [...str]; // ['h','e','l','l','o']
对象展开 (ES2018)
// 对象复制 (浅拷贝)const obj = { a: 1, b: { c: 2 } };const clone = { ...obj };// 对象合并const defaults = { theme: "light", fontSize: 16 };const userSettings = { fontSize: 18, darkMode: true };const settings = { ...defaults, ...userSettings };// { theme: "light", fontSize: 18, darkMode: true }
其他的扩展运算符用法可以看这里数组一些常用的方法
最后
end ,参考【JS高级程序第四版】,阮一峰ES6入门 运算符的扩展