深層屬性,輕鬆提取

圖片描述

面臨的問題

假設有這樣一個對象,表示的是 用戶是否啓用了回覆通知的設置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 獲取

相關文章
相關標籤/搜索