深层属性,轻松提取

图片描述

面临的问题

假设有这样一个对象,表示的是 用户是否启用了回复通知的设置git

const settings = {
    notification: {
        reply: {
            active: {
                true
            }
        }
        // ...其余设置项
    }
    // ...其余设置项
}

当开发者想要提取 active 的值,最直接的方法是这么作github

const isNotificationReplyActive = settings.notification.reply.active

但这是不安全的,由于 JavaScript 中一般使用 nullundefined 分别表示未定义或未声明的值npm

typeof someVar === 'undefined' // 未声明
let someVar = null // 已声明,未定义

实际开发过程当中可能由于好比节省资源的考虑,当用户未进行过设置时,它的 notification 或者更深的某一级的值是 nullundefined,而非对象。安全

// 好比当未设置回复通知时,它是这样的
const settings = {
    notification: {
        // 没有 reply
    }
}

// 这种状况下, settings.notification.reply 的值是 undefined
// JS 中试图获取 undefined 上的 key 时会触发 TypeError
const isNotificationReplyActive = settings.notification.reply.active // TypeError!

因而开发者采起了这样的措施dom

const isNotificationReplyActive = settings
    && settings.notification
    && settings.notification.reply
    && settings.notification.reply.active
// 或者
try {
    const isNotificationReplyActive = settings.notification.reply.active
} catch (err) {
    // 错误处理
}

经验丰富的开发者都知道,这样作的缺点不少,在此就不展开了。编辑器

因而一些工具函数诞生了,好比 lodash 的 _.get函数

import _ from 'lodash'
const isNotificationReplyActive = _.get(settings, 'notification.reply.active')

虽然它保证了开发者在提取属性的过程当中不会由于遇到 undefinednull 之类的值而抛出 TypeError ,但缺点也很明显——工具

  1. 属性的路径被写成了字符串,开发者没法得到 IDE/编辑器 的自动补全与智能纠错。
  2. 不能使用便捷的解构语法—— const { notification: { reply: { active } } } = settings

简直是一晚上回到解放前。spa

解决方法 —— safe-touch

如今让咱们来回顾一下本文开头的那张图——它便是本文的主角、上述全部问题的解决方案。code

// 引入
import safeTouch from 'safe-touch'

const settings = { /* ... */ }
// 包裹要提取的对象
const touched = safeTouch(settings)

// 把它看成函数调用,能够得到原始值
touched() === settings // true

// 亦能够直接获取 settings 上存在的属性,一样经过调用取得属性值
// 在现代化的 IDE/编辑器 中,这一过程能够给出智能提示与自动补全
touched.notification.reply.active() // 若依本文开头给出的例子,值为 true

// 能够安全地获取并不存在的属性,返回 undefined ,不会抛出 TypeError
touched.something.does.not.exist[Math.random()]() // undefined

// 支持解构
const { notification: { reply: { active, notExistingKey } } } = touched
active() // true
notExistingKey() // undefined

怎么作到的

其实不难,核心功能经过 ES6 的 Proxy 就能够实现。再结合 TypeScript 的类型判断(初学 TS,看了很久文档),生成 index.d.ts 供智能化的 IDE/编辑器 使用,就有了自动补全与智能提示。

短小的源码 repo (欢迎 Star / issue)

能够从 npm 获取

相关文章
相关标签/搜索