1

页面白屏了?看看可选链操作符(?.)

 3 years ago
source link: https://segmentfault.com/a/1190000040029674
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

今天又被 QA 找: 这个页面昨天还好好的, 今天就白屏了, 是不是你代码有问题啊, 赶紧看看。

上去一看, 找到了原因:

原本 pickup, dropoff 两个字段没有数据的话, 应该返回{}, 结果现在pickup字段返回了null, 而我们取值的时候,也没对这个地方做防御。

list: openApiOrderInfo.pickup.address_list,

结果就是:脚本报错, 页面不可用。

解决起来也很简单, 要么给个默认值, 要么使用 ?. 做一层防御。

改完再试一下, 就 OK 了, 页面恢复正常。

下面我们就说一下这个 ?.

今天的主要内容:

  • 什么是可选链操作符(?.)
  • 如何启用这个功能
  • 可选链操作符(?.) 是如何工作的
  • Henry发布的相关些资料

可选链操作符(?.), 大家都很熟悉了,这里再简单回顾一下。

什么是可选链操作符(?.)

可选链操作符(?.)允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。

比如,思考一个存在嵌套结构的对象 obj。不使用可选链的话,查找一个深度嵌套的子属性时,需要验证之间的引用,例如:

let nestedProp = obj.first && obj.first.second;

为了避免报错,在访问obj.first.second之前,要保证 obj.first 的值既不是 null,也不是 undefined。

如果只是直接访问 obj.first.second,而不对 obj.first 进行校验,则有可能抛出错误。

有了可选链操作符(?.),在访问 obj.first.second 之前,不再需要明确地校验 obj.first 的状态,再并用短路计算获取最终结果:

let nestedProp = obj.first?.second;

这等价于以下表达式,但实际上没有创建临时变量:

let temp = obj.first;
let nestedProp = ((temp === null || temp === undefined) ? undefined : temp.second);

?. 操作符的功能类似于 . 链式操作符,不同之处在于:

在引用为空(nullish) (null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是: undefined

与函数调用一起使用时,如果给定的函数不存在,则返回 undefined

当尝试访问可能不存在的对象属性时,使用可选链操作符将会使表达式更短、更简明

有两点需要我们留意:

  1. 如果存在一个属性名且不是函数, 使用 ?. 仍然会产生一个 TypeError 异常 (x.y is not a function).
let result = someInterface.customMethod?.();

如果 someInterface 自身是 null 或者 undefined ,异常 TypeError 仍会被抛出。

如果你希望允许 someInterface 也为 null 或者 undefined,那么你需要像这样写 someInterface?.customMethod?.()

  1. 可选链不能用于赋值
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment

如何启用这个功能

// install
npm install --save-dev @babel/plugin-proposal-optional-chaining

// babel config
{
 "plugins": [
    "@babel/plugin-proposal-optional-chaining" //可选链
    "@babel/plugin-proposal-nullish-coalescing-operator", //双问号
  ]
}

可选链操作符(?.) 是如何工作的

const a = {
  b: 1
};

console.log(a?.b);

会被转换成:

const a = {
  b: 1
};

console.log(a === null ? void 0 : a.b);

如果层级更深, 会创建临时变量用于记录:

const a = {
  b: {
    c: 1,
    d: 2,
  }
};

console.log(a?.b?.c)

会被转换成:

var _a$b;

const a = {
  b: {
    c: 1,
    d: 2
  }
};
console.log(
  a === null || a === void 0
    ? void 0 
    : (_a$b = a.b) === null || _a$b === void 0
      ? void 0
      : _a$b.c
);

Heny发布的相关些资料

Heny 目前是 babel 项目的负责人,之前发过一片介绍当前 babel 困境的文章。

上图推文链接:https://twitter.com/left_pad/...

感兴趣的可以去看看。

?. 使用起来是非常方便的, 但如果用的不好, 也会隐藏本应该暴露出来的问题。

所以, 使用的时候一定要清楚自己在做什么。

?. 还有个小兄弟叫 空值合并运算符(??), 这里就不说了, 去 MDN 看文档吧。

今天就这么多, 希望对大家有所启发。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK