Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

解构赋值被滥用? #318

Open
toFrankie opened this issue Jul 22, 2023 · 0 comments
Open

解构赋值被滥用? #318

toFrankie opened this issue Jul 22, 2023 · 0 comments
Labels
2023 2023 年撰写 JS 与 JavaScript、ECMAScript 相关的文章 前端 与 JavaScript、ECMAScript、Web 前端相关的文章

Comments

@toFrankie
Copy link
Owner

toFrankie commented Jul 22, 2023

配图源自 Freepik

开始

某天看到这样一个老帖子调侃道:

// let inputClass = manager.options.inputClass
let { options: { inputClass } } = manager

不可否认,ES6 的解构赋值(Destructuring Assignment)语法在日常开发中带来了极大的便利。但是...

看起来不错

有一个对象,

var store = {
  name: 'Apple Store Parc Central',
  national_code: '86',
  phone: '4006139742'
}

若要将其属性值赋予新变量,在 ES5 及以前,

var name = store.name
var phone = store.phone

在 ES6 及以后,

const { name, phone } = store
const { national_code: nationalCode } = store

到目前为止,看起来很不错。

看起来还行

若是一个嵌套类型的对象,

const store = {
  name: 'Apple Store Parc Central',
  national_code: '86',
  phone: '4006139742',
  address: {
    province: 'Guangdong',
    city: 'Guangzhou',
    county: 'Tianhe',
    street: 'No. 218, Tianhe Road',
  }
}

一部分同学可能会这样用,

const { address: { province, city } } = store

而我个人更偏向于,

const { province, city } = store.address

为什么呢?

假设数据源 store 来自于别处,其中 store.address 可能是一个不存在的属性,为避免解构出错,我们可能会为其设置默认值。比如:

const { address: { province, city } = {} } = store

const { province, city } = store.address || {}

个人认为后者更直观一些,这也是我选择它的原因之一。

前者还有个陷进,如果 store.addressnull,默认值就不生效,自然解构也会出错。

但如果要获取不同层级的属性时,也会像前面那样用,

const { name, address: { province, city } } = store

看起来不好!

若对象时一个嵌套多层的对象,

const store = {
  name: 'Apple Store Parc Central',
  national_code: '86',
  phone: '4006139742',
  address: {
    province: 'Guangdong',
    city: 'Guangzhou',
    county: 'Tianhe',
    street: 'No. 218, Tianhe Road',
  },
  activity: {
    today: {
      name: '光影技巧:用 iPhone 拍摄照片',
      description: '用 iPhone 拍出更棒的照片和视频。',
      start_at: '1690090200',
      end_at: '1690093800',
    },
  },
}

就可能会出现这种令人抓狂的写法,

const {
  activity: {
    today: { start_at: startAt },
  },
} = store

// or
const { activity: { today: { start_at: startAt } = {} } = {} } = store

给人的感觉是「为了用而用」。

为什么不用最原始的方式?忘本了?

const startAt = store.activity.today.start_at

即使这样,可读性也比前面的好吧,

const { start_at: startAt } = store.activity.today

新语法固然是为了解决某种场景而生的,但其并非适用于所有场景的啊。有句话怎么说来着:「因地制宜」。

那应该怎么写?

解构赋值语法允许指定默认值。但当属性值为 null 时,并不会赋予默认值。假设以下 store.activitynull 时,解构会出错,

const { activity: { today: { start_at: startAt } = {} } = {} } = store

我们可能还是要这样写,

const startAt = store && store.activity && store.activity.today ? store.activity.today.start_at : undefined

在这篇文章有一种写法,

const getPropValue = (obj, key) => {
  return key.split('.').reduce((o, x) => (o == undefined ? o : o[x]), obj)
}

const startAt = getPropValue(store, 'activity.today.start_at') // "1690090200"

对于获取深层属性的情况,很多工具库都有提供现成的方法,感兴趣可看下实现。比如:

后来,ES2020 增加了可选链(Optional Chains)语法 ?.,就可以这样去写了:

const { province, city } = store?.address || {}

const startAt = store?.activity?.today?.start_at

当某个属性值为空值(nullishundefined or null),则短路返回 undefined

最后

解构赋值虽好,但不要贪杯哦!

@toFrankie toFrankie added 前端 与 JavaScript、ECMAScript、Web 前端相关的文章 JS 与 JavaScript、ECMAScript 相关的文章 2023 2023 年撰写 labels Jul 22, 2023
@toFrankie toFrankie changed the title 细读 ES6 | 解构赋值被滥用? 解构赋值被滥用? Jul 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
2023 2023 年撰写 JS 与 JavaScript、ECMAScript 相关的文章 前端 与 JavaScript、ECMAScript、Web 前端相关的文章
Projects
None yet
Development

No branches or pull requests

1 participant