解构赋值默认值误区

综合技术 2018-05-18 阅读原文

问题还原

这是最近 CR 的时候在业务代码中发现了一个问题,先来看一下问题代码:

// data 为接口返回的数据
const { bizObject = {}, total = 0 } = data.result || {};
const list = bizObject.list || [];

// 其他逻辑,比如把 list 更新到 state 中,等等
  • A 接口正常的情况: data
    中有 result
    属性,且 result
    对象中 bizObject
    返回了一个数—— :white_check_mark:
  • B 接口异常: data
    对象中没有 result
    属性 —— :white_check_mark:
  • C 接口异常: data
    中有 result
    属性, result
    对象中也有 bizObject
    属性,但是, bizObject
    属性的值是 null
    ,然后呢?

从上下文来看,这位同学应该是期望解构赋值按以下方式执行:

const result = data.result || {};
const bizObject = result.bizObject || {};
// ...

但是,C 情形抛异常了:

Uncaught TypeError: Cannot read property 'list' of null

也就是 bizObject
的值是 null
而不是期望的 {}
。为什么呢?

解构赋值中的默认值

A variable can be assigned a default, in the case that the value unpacked from the object/array is undefined
.

数组、对象解构赋值时,只有当属性(数组索引对应的值)值为 undefined
时,才会使用默认值。

问题代码中,当 bizObject
null
时,解构出来的就是 null
,读取 null
list
属性,不报错才怪。

函数默认参数

再来看看函数的默认参数是不是同样的逻辑:

function doSomething(options = { foo: 'bar' }) {
  console.log(options);
}

doSomething(); // { foo: "bar" }
doSomething(undefined); // { foo: "bar" }
doSomething(null); // null

不传参数(隐式的 undefined
)或者显示地传递 undefined
,使用了默认参数,传 null
的时候没有使用默认值,和解构赋值的默认值同样的逻辑。

其实把上面的函数转成 ES5,就能直观地了解其逻辑:

function doSomething() {
  var options =
    arguments.length > 0 && arguments[0] !== undefined
      ? arguments[0]
      : {
          foo: "bar"
        };
  console.log(options);
}

解构赋值的默认值也一样:

// ES6
const { a = 1 } = { };

// 转换成 ES5
var _ref = {},
  _ref$a = _ref.a,
  a = _ref$a === void 0 ? 1 : _ref$a;

写在最后

之所以会有同学把解构赋值默认值等同于 const bizObject = result.bizObject || {}
,可能是对 ES6 的一些细节了解得不够透彻,可以多翻翻文档:

还有一个可能,前端同学并没有误解解构赋值默认值的工作原理,只是接口不规范引发了异常。一般而言,
接口约定好字段、类型后,就应该始终按约定的类型返回数据,约定的是对象,那没有数据的时候也应该返回一个空对象,即使不返回这个字段,前端也已经判断了,莫名其妙地返回一个 null
算哪门子事

接口写得有问题,有的人沟通一下还是会调整,有的人就始终一副「放荡不羁」样子,通了就行,才不管你什么规范、约定……对于不讲究的人,还是自己多写两行代码判断一下,说多了也是浪费,你懂的。

很多事情都是 100% 的期望,然后妥协,接受一个差不多的结果。(BGM 差不多先生 - MC Hot Dog

责编内容by:CSSPod 【阅读原文】。感谢您的支持!

您可能感兴趣的

Stop a function if the function has obtained a new... I need help with my javascript function If a user clicks an element with this event listener... onmousedown=&qu...
JavaScript Frameworks 2018: Choose What’s Trending... JavaScript is a leading choice of all the developers across the globe for designing their web and mob...
看过这篇文章以后不要再提this 序言:本文是 《 前端3小时速成指南 - 写代码啦! 》中其中关于 this 讲解的文字版教程,本周日(12月10日晚8点)有 前端3小时速成指南后半部分免费直播课,讲解 继承、this、Web ...
List of Useful libraries for your next React Web A... I have list down various libraries that you can use for your next react project. You can find all these libraries ...
管你以后写不写JS,都应该学会这种思考方式... 昨天的文章喷了下程序员写不过35这种说法,但事实上,确实并不能每个人都像我一样,在写JS中找到乐趣,就乐意写这东西直到50岁眼瞎为止。 那肯定有人要问,也许我不仅写JS写不到35,可能我连3、5年的时间都写不到。那我学JS的...