夢見がちWeb屋の浮かれ雑記帳

フロントエンド周りの技術ネタやらなんやらね

JavaScriptでネストしたオブジェクトのプロパティへのアクセスを工夫してみる

例えばRubyだとSafe Navigation Operator(&.)を使えばネストしたプロパティに安全にアクセスできる。

name = product&.retailer&.name

とやれば

retailerの部分がnilでも例外を吐かずにnameが安全にnilになる。

これをJavaScriptでもやりたいぜ。

もちろん言語レベルではそんなもんなはないので、何にかしらの工夫が必要。

RFCで提唱されている仕様としてはJSON Pointerというやつがあって、これを使えばName Pathからのアクセスが実現できる。

実装としてはnpmにjson-pointerというモジュールが登録されていて、

const { get, set } = require('json-pointer')

let product = { /* ... */ }
set(product, '/retailer/name', "あいうえお商店")
let retailerName = get(product, '/retailer/name')
/* ... */

みたいな感じで使える。

あら便利!と思ってしばらく使ってみた。

が。

やっぱめんどくせぇ。。。

Name Pathが直感的じゃないのだ。取得のたびに関数に渡すのも微妙。

もっと良い術がないか。ないな。探した限り。じゃあ作るか。

そして作ったのがこれ ↓↓

github.com

Pathを指定してアクセスするのをやめた。代わりShallowな構造とDeepな構造を相互変換できるようにした。

flatten(nested)で、Nest構造を平たいオブジェクトに変換する。その際、プロパティ名は"."つなぎになる

const { flatten } = require('objnest')

let flattened = objnest.flatten({
    'foo': {'bar': 'baz'}
})
console.log(flattened) // => {'foo.bar': 'baz'}

逆に構造化したい場合はexpand(flattend)する。"."つなぎのプロパティがネストされたオブジェクトになる。

const { expand } = require('objnest')

let expanded = expand({
    'foo.bar': 'baz'
})
console.log(expanded) // => {foo: {bar: 'baz'}}

使って見るとこれがなかなか便利。Reactの高速化の時にShallowCompareで扱えるようにしたりね。ビバ俺様仕様。

参考