惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
Y
Y Combinator Blog
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
Martin Fowler
Martin Fowler
博客园_首页
大猫的无限游戏
大猫的无限游戏
美团技术团队
S
SegmentFault 最新的问题
T
The Blog of Author Tim Ferriss
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MyScale Blog
MyScale Blog
小众软件
小众软件
Vercel News
Vercel News
阮一峰的网络日志
阮一峰的网络日志
N
Netflix TechBlog - Medium
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
量子位
博客园 - 【当耐特】
J
Java Code Geeks
F
Fortinet All Blogs
宝玉的分享
宝玉的分享
Stack Overflow Blog
Stack Overflow Blog
博客园 - 司徒正美

蚊子的前端博客

微说 | 有的人觉得只要不考XX,一定能考好!-蚊子的前端博客 微说 | 春天来了-蚊子的前端博客 明天和意外不知道哪个先来-蚊子的前端博客 微说 | 既然错过了路口,就及时止损,重新规划路线上路-蚊子的前端博客 微说 | 2025年的出生人口数是792万-蚊子的前端博客 微说 | 工作年终总结,让写对接的接口的数量?-蚊子的前端博客 微说 | 温家宝:没有政治体制改革的成功 经济体制改革不可能进行到底-蚊子的前端博客 微说 | 违法犯罪了该不该被禁言?-蚊子的前端博客 微说 | 不明白为什么在推荐去俄罗斯旅游-蚊子的前端博客 微说 | 易中天论骗子-蚊子的前端博客 微说 | 一场大风吹散了秋天-蚊子的前端博客 微说 | 既要、又要、还要、更要!-蚊子的前端博客 又是一年的国庆雨季-蚊子的前端博客 微说 | 预估下2025年的出生人口数据-蚊子的前端博客 微说 | 可惜了我那些小时候的书本-蚊子的前端博客 微说 | 牛马有的是,驴不够了!-蚊子的前端博客 微说 | 能否有一条非户口也能高考的路-蚊子的前端博客 微说 | 小聊中医-蚊子的前端博客 微说 | 将要制作的一款新产品-蚊子的前端博客 微说 | 做人要有信-蚊子的前端博客 微说 | 好一个正义联盟-蚊子的前端博客 微说 | 都是见过吃过的主儿-蚊子的前端博客 微说 | 追求8小时工作制有错吗?-蚊子的前端博客 微说 | 如果尖锐的批评完全消失-蚊子的前端博客 微说 | 很好!-蚊子的前端博客 微说 | 封禁用户可以,但要告知具体原因-蚊子的前端博客 微说 | 面朝大海,春暖花开-蚊子的前端博客 微说 | 程序员的悲哀是什么?-蚊子的前端博客 微说 | 2025年出生人口的预测-蚊子的前端博客 前端在 LiveKit 中如何获取所有的参与者-蚊子的前端博客
JS 中一些高效的魔法运算符-蚊子的前端博客
author · 2021-04-29 · via 蚊子的前端博客

这两天有同事说我挺久没更新文章了,不过最近一段时间确实有点忙,一直在忙着两个活动中心的改版,没什么时间来更新文章。今天终于抽空可以写一写。

高高兴兴

JavaScript 现在每年都会发一个新版本,里面也会新增一些操作更加便利、高效的运算符。今天我们就来盘点下几个高效的魔法运算符。

1. 可选链运算符 #

之前当我们想要使用某个结构比较深的属性,同时又无法确定所有的父级一定存在时,我们需要进行一连串的判断,例如一个数据结构:

const student = {
  score: {
    math: 98,
  },
};

我们想要获取最内层的 math 属性的值时:

if (student && student.score) {
  console.log(student.score.math);
}

1.1 获取深层次的属性 #

不过当我们使用可选链运算符后,判断就简单很多了,可选链运算符会在链路上遇到 null 或者 undefined 时,直接返回 undefined,而不会抛出错误异常:

console.log(student?.score?.math);

1.2 执行一个可选的方法 #

同时在执行一个可能存在的函数时,也可以用到。例如一个 react 组件中,传入的方法是可选的:

// getScore 是一个可选参数,要么是 undefined,要么是一个函数
const Student = ({ getScore }: { getScore?: () => void }) => {
  useEffect(() => {
    // 当 getScore 存在时,正常执行 getScore()方法
    getScore?.();
  }, []);

  return <div></div>;
};

或者我们执行一个 dom 元素的方法时,也可以使用。

document.querySelector 会返回两种类型,当 dom 元素真实存在时会返回该元素,否则返回 null。写过 typescript 的都知道,当我们要调用某个方法时,总是要先确定该 dom 元素是存在的:

const dom = document.querySelector('.score');
if (dom) {
  dom.getBoundingClientRect(); // 当 dom 元素存在时,才执行该方法
}

使用可选链操作符时,就直接调用即可:

document.querySelector('.score')?.getBoundingClientRect();

1.3 获取数组中的值 #

若数组存在,则获取某个下标的值,我们现在也不用再判断数组是否存在了,可以直接使用:

arr?.[1]; // 若 arr 存在时,则正常获取 arr[1]中的值

上面的 3 种情况也是可以组合使用的。若一个结构比较复杂时,各种类型都有,这里我们要执行数组 math 下标 2 的方法:

const student = {
  score: {
    math: [
      98,
      67,
      () => {
        return 99;
      },
    ],
  },
};

执行:

student?.score?.math?.[2]?.(); // 99

还有这种操作?

1.4 无法进行赋值操作 #

可选链运算符只能执行获取操作,是无法进行赋值操作的。

例如给一个可能的数组或者 dom 元素赋值时,会直接抛出语法异常:

arr?.[1] = 2; // x
document.querySelector('.score')?.innerHTML = 98; // x

当我们执行上面的语句时,会抛出如下的提示:

Uncaught SyntaxError: Invalid left-hand side in assignment

即不能给左侧的可选链进行赋值操作。

2. 双问号运算符 #

双问号运算符??,我理解是为了解决或运算符||而设计出来的。

我们先来回顾下或运算符的操作,当左侧的数据为假值(数字 0, 布尔类型的 false,空字符串,undefined, null)时,则执行右侧的语句。

false || 123;
0 || 123;
'' || '123';
undefined || 123;
null || 123;

可是在有些情况下,false 和 0 都是正常的值,但若使用或运算符时,会导致出错。

比如下面的这个例子,当 score 为空时,则默认值为 1。当输入正常值 0 时应当返回 0(但实际上返回了 1):

const getSCore = (score: number) => {
  return score || 1;
};

getScore(0); // 1

这时,我们就用到了双问号运算符??。双问号运算符只会在左侧为 undefined 或者 null 时,才会执行右侧的语句。

const getSCore = (score: number) => {
  return score ?? 1;
};

getScore(0); // 0

同时,双问号运算符还可以与=结合成为一个赋值操作,当左侧为 null 或者 undefined 时,则将右侧语句的结果赋值给左侧的变量:

score ??= 1; // 1

我读书多,不会骗你

3. 或运算和与运算的赋值操作 #

我们在之前使用或运算符进行赋值操作时,是这样写的:

score = score || 1;
age = age && 24;

现在可以直接简写成:

score ||= 1; // 等同于 score = score || 1
age &&= 24; // 等同于 age = age && 24

4. 双星号运算符 #

双星号运算符**是比较早引入到 js 中的,只是我们用到的比较少而已。其实它执行的是一个幂运算,等同于 Math.pow()。

2 ** 10; // 1024, 2的10次方,等同于 Math.pow(2, 10);

5. 总结 #

以上所有的样例均已在 chrome90 上运行通过。

棒棒哒

我们在已经有 babel 帮助转换的情况下,可以适当的在代码运用这些运算符,能够极大地简化我们的代码。