js 提升开发效率的运算符汇总

1,292 阅读10分钟

前言

Javascript(ECMAScript) 自 ES6 之后在每年的 6月 都会进行一次版本更新,每每都会新增一些实验性的语法、运算符等,迄今为止已经增加了不少新成员,本文就介绍一些开发中能简化代码提升开发效率的运算符,走你~~

赋值运算符

1. ++(自增运算)

自增运算符,a++ 效果等同 a = a + 1

在使用 ++、-- 运算符时,要非常注意前置和后置的使用对返回值的影响,有些时候这将带来难以发现的麻烦。

// 后置
var a = 1
a++ // => 1
console.log(a) // => 2

// 前置
var a = 1
++a // => 2
console.log(a) // => 2
2. --(自减运算)

自减运算符,a-- 效果等同 a = a - 1

// 后置
var a = 2
a-- // => 2
console.log(a) // => 1

// 前置
var a = 2
--a // => 1
console.log(a) // => 1

算术运算符

1. ** (幂运算)

求幂运算符(**)返回将第一个操作数加到第二个操作数的幂的结果。它等效于 Math.pow(),不同之处在于它也接受 BigInts 作为操作数。

2 ** 3   // 8
3 ** 2   // 9
3 ** 2.5 // 15.588457268119896
10 ** -1 // 0.1
NaN ** 2 // NaN

一元运算符

1. void

void 运算符 对给定的表达式进行求值,然后返回 undefined

立即调用的函数表达式:

在使用立即执行的函数表达式时,可以利用 void 运算符让 JavaScript 引擎把一个 function 关键字识别成函数表达式而不是函数声明(语句)。

void function iife() { alert('iife') }();
JavaScript URIs

当用户点击一个以 javascript: 开头的URI 时,它会执行URI中的代码,然后用返回的值替换页面内容,除非返回的值是undefined。void运算符可用于返回undefined。例如:

<a href="javascript:void(0);">
  这个链接点击之后不会做任何事情,如果去掉 void(),
  点击之后整个页面会被替换成一个字符 0。
</a>
<p> chrome中即使<a href="javascript:0;">也没变化,firefox中会变成一个字符串0 </p>
<a href="javascript:void(document.body.style.backgroundColor='green');">
  点击这个链接会让页面背景变成绿色。
</a>

注意,虽然这么做是可行的,但利用 javascript: 伪协议来执行 JavaScript 代码是不推荐的,推荐的做法是为链接元素绑定事件。

在箭头函数中避免泄漏

箭头函数标准中,允许在函数体不使用括号来直接返回值。 如果右侧调用了一个原本没有返回值的函数,其返回值改变后,则会导致非预期的副作用。 安全起见,当函数返回值是一个不会被使用到的时候,应该使用 void 运算符,来确保返回 undefined(如下方示例),这样,当 API 改变时,并不会影响箭头函数的行为。

button.onclick = () => void doSomething();
注意 void 运算符的优先级

在下面两行代码中,由于第一行代码没有使用小括号运算符,则 void 运算符优先执行,返回值 undefined 再与 1 执行减法运算,所以返回值为 NaN。在第二行代码中由于使用小括号运算符明确 void 的操作数,减法运算符先被执行,然后执行 void 运算,最后返回值是 undefined

console.log(void 2 - 1);  //返回NaN
console.log(void (2 - 1));  //返回undefined
2. +(一元加运算符)

一元加运算符,可将操作数转换为 Number 类型,效果等价于 Number() 方法,日常开发中可以替代 Number() 方法使用,简化代码。

var a = '222'
var b = 'abc'
console.log(+a) // => 222
console.log(+b) // => NaN

console.log(Number(a)) // => 222
console.log(Number(b)) // => NaN
3. -(一元减运算符)

一元减运算符:

  • 对数字使用:返回数字的负数;
  • 对其他数据类型使用:首先尝试把表达式转换成数字,再取负数;
var a = 3
console.log(-a) // => -3

var b = false
console.log(-b) // => -0

-0 === +0,

4. !(逻辑非)

逻辑非运算符,将操作数转化为布尔值后进行取反操作,与 Boolean() 效果相同。

!true      // false
!false     // true
!''        // true
!'Cat'     // false
!!(双非)

可以使用两个 ! 运算符来强制将任何值转换为相应的布尔值。转换基于值的

n1 = !!true                   // true
n2 = !!{}                     // true
n3 = !!(new Boolean(false))   // false
n4 = !!false                  // false
n5 = !!""                     // false
n6 = !!Boolean(false)         // false
5. ~( 位非)

按位非运算符,反转操作数的位。

const a = 5;     // 00000000000000000000000000000101
const b = -3;    // 11111111111111111111111111111101

~a               // 11111111111111111111111111111010
console.log(~a); // -6

~b		 // 00000000000000000000000000000010
console.log(~b); // 2

位非运算实际上就是对数字进行取负运算,再减 1。例如:

console.log(~12 == -12 - 1));  // true

实际开发中可应用的场景:

indexOf() 返回值 >= 0 或者是 -1,使用 ~ 判断值为 -1 的场景。

var a = 'abcdefg'
if(!(~a.indexOf('ddd'))) {
	// 替代 a.indexOf('ddd') === '-1' 的写法
}
~~(双位非)

可以使用两个 ~~ 按位非来替代正数的 Math.floor( ),替代负数的 Math.ceil( )

不过要注意,对正数数值来说 ~~ 运算结果与 Math.floor( ) 运算结果相同,而对于负数数值来说与 Math.ceil( ) 的运算结果相同:

~~4.5                // 4
Math.floor(4.5)      // 4
Math.ceil(4.5)       // 5

~~-4.5        	     // -4
Math.floor(-4.5)     // -5
Math.ceil(-4.5)      // -4

逻辑位运算符与逻辑运算符的运算方式是相同的,但是针对的对象不同。逻辑位运算符针对的是二进制的整数值,而逻辑运算符针对的是非二进制的值。

6. & (位与)

“&” 运算符(位与)用于对两个二进制操作数逐位进行比较,并根据下表所示的换算表返回结果。

“&”运算符换算表:

第一个数的位值第二个数的位值运算结果
111
100
010
000

在位运算中,数值 1 表示 true,0 表示 false,反之亦然。

12 和 5 进行位与运算,则返回值为 4。

console.log(12 & 5);  // 4

// 对数字 a & 1可以判断奇偶数,负数也同样适用,num & 1
console.log(11 & 1) // 1
console.log(12 & 1) // 0

下图以算式的形式解析了 12 和 5 进行位与运算的过程。通过位与运算,只有第 3 位的值为全为 true,故返回 true,其他位均返回 false。 在这里插入图片描述

7. |(位或)

“|”运算符(位或)用于对两个二进制操作数逐位进行比较,并根据如表格所示的换算表返回结果。

“|”运算符换算表:

第一个数的位值第二个数的位值运算结果
111
101
011
000

12 和 5 进行位或运算,则返回值为 13。

console.log(12 | 5);  // 13

// 对一个数字| 0可以取整,负数也同样适用,num | 0

1.3 | 0         // 1
-1.9 | 0        // -1

下图以算式的形式解析了 12 和 5 进行位或运算的过程。通过位或运算,除第 2 位的值为 false 外,其他位均返回 true。 在这里插入图片描述 在这里插入图片描述

8.^(位异或)

“^”运算符(位异或)用于对两个二进制操作数逐位进行比较,并根据如表格所示的换算表返回结果。

“^”运算符换算表:

第一个数的位值第二个数的位值运算结果
110
101
011
000

12 和 5 进行位异或运算,则返回值为 9。

console.log(12 ^ 5);  //返回值9

下图以算式的形式解析了 12 和 5 进行位异或运算的过程。通过位异或运算,第 1、4 位的值为 true,而第 2、3 位的值为 false。 在这里插入图片描述

二元运算符

1. ,(逗号运算符)

逗号运算符是二元运算符,它能够先执行运算符左侧的操作数,然后再执行右侧的操作数,最后返回右侧操作数的值。

逗号运算符可以实现连续运算,如多个变量连续赋值。

var a = 1, b = 2, c = 3, d = 4;

等价于:

var a = 1;
var b = 2;
var c = 3;
var d = 4;

与条件运算符、逻辑运算符根据条件来决定是否执行所有或特定操作数不同的是,逗号运算符会执行所有的操作数,但并非返回所有操作数的结果,它只返回最后一个操作数的值。

在下面代码中,变量 a 的值是逗号运算之后,通过第二个操作数 c=2 的执行结果赋值得到的。第一个操作数的执行结果没有返回,但是这个表达式被执行了。

a = (b = 1, c = 2);  //连续执行和赋值
console.log(a);  //返回2
console.log(b);  //返回1
console.log(c);  //返回2

提示 逗号运算符可以作为仅需执行表达式的工具,这些表达式不需要返回值,但必须要运算。在特定环境中,可以在一个表达式中包含多个子表达式,通过逗号运算符让它们全部执行,而不用返回结果。

for 循环结构的小括号内包含 3 个表达式,第一个表达式为初始化值,第二个表达式为检测条件,第三个表达式为递增表达式。使用逗号运算符可以在 3 个表达式中添加多个额外的计算任务,但要确保第二个表达式的最后一个子表达式返回一个可控布尔值,否则会导致死循环。

for(var a = 1, b = 10, c = 100; ++c, a < b; a++, c--){
    console.log(a * c);
}

逗号运算符的优先级是最低的。在下面代码中,赋值运算符优先于逗号运算符,也就是说数值 1 被赋值给变量 b 之后,继续赋值给变量 a,最后才执行逗号运算符。

a = b = 1,c = 2;  //连续执行和赋值
console.log(a);  //返回1
console.log(b);  //返回1
console.log(c);  //返回2

三元运算符

1. ?:(条件运算符)

三元条件运算符,val(判断值)为真,取前者(问号后),为假取后者(冒号后)。

const val = 1
val ? 'val为真' : 'val为假' // => 'val为真'

二元逻辑运算符

1. ??(空值合并运算符)

如果 ?? 前面是 nullundefined,取后面的默认值

null ?? 3      //3
undefined ?? 3 //3
7 ?? 3        //7
2. &&(逻辑与)

取假运算,从左往右执行,遇到假值就返回该假值,停止执行后续,否则就返回遇到的最后一个真值。

var [a, b, c] = [1, false, 0]
console.log(a && c) // => 0
3. ||(逻辑或)

取真运算,从左往右执行,遇到真值就返回该真值,停止执行后续,否则就返回遇到的最后一个假值。

var [a, b, c] = [1, false, 0]
console.log(b || c || a) // => 1

其他

1. ...(扩展运算符)

可以在函数调用/数组构造时, 将 数组表达式 或者 字符串 在语法层面展开;还可以在构造字面量对象时, 将对象表达式按 key-value 的方式展开,在实际开发中非常常见。

字面量一般指 [1, 2, 3] 或者 {name: "mdn"} 这种简洁的构造方式

// 展开数组
const numbers = [1, 2, 3];
console.log([...numbers]) // => [1, 2, 3]

// 展开字符串
const strings = '1234567';
console.log([...strings]) // => [1, 2, 3, 4, 5, 6, 7]

// 展开对象
const person= { name: 'Ryan', gender: '男' }
console.log({...person}) // => { name: 'Ryan', gender: '男' }

// 函数调用中使用
const numbers = [1, 2, 3];
function sum(x, y, z) {
  return x + y + z;
}
console.log(sum(...numbers)) // => 6

// 解构时使用
const person = { name: 'Alex', gender: '男', age: 18 }
const { age, ...rest } = person

console.log(age, {...rest}) // => 18,{ name: 'Alex', gender: '男' }

当数组的值或者对象的键值都为基本类型时,[...],{...} 运算符可以实现对象或数组的深拷贝,反之只能实现浅拷贝。

2. ?.(可选链操作符)

在引用的属性为空 (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

const person = {
  name: 'Alex',
  cat: {
    name: 'tom'
  }
};

const tomName= person.dog?.name;
console.log(tomName);
// 返回 undefined

console.log(person.someNonExistentMethod?.());
// 返回 undefined

可以完全取代开发中使用的 a && a.children && a.children.name 的场景。

参考链接:

持续更新中。。。觉得不错点个收藏吧 ☆~~~