社内での質問がきっかけで高階関数でなんとかなりそうと思いサクッと作ってみたのでメモ。
オブジェクトがない場合は空オブジェクトを自動で作成するようになっているので最近話題のOptional Chainingとはちょっと違います。
# タイトルの「安全に」はオブジェクトなくても子や孫のツリーを実現できる意図でつけました、nullやnumberなどに対してオブジェクトを追加しようとするとエラーになります
# コメントで0や''といったfalsyが値としてセットできない指摘がありましたのでnullも入るように修正しました、ありがとうございます
/**
* Create, Read, Update, Delete
*/
function crud(obj, key, value) {
let result = obj[key];
if ((typeof result) === 'undefined') { // 値がまだなければ空オブジェクトで初期化
result = obj[key] = {};
}
if ((typeof value) !== 'undefined') { // value指定ありの場合は値を書き換える
result = obj[key] = value;
}
// key指定なしの場合はチェーンで呼べる無名関数ではなく値そのものを返す(Read用途)
return (key, value) => (typeof key) !== 'undefined' ? crud(result, key, value) : result;
}
var obj = {};
// [Create + Update] obj.a.b.c = 123;
crud(obj, 'a')('b')('c', 123);
// [Read] obj.a.b.c;
console.log(
crud(obj, 'a')('b')('c')()
); // 123
// [Delete] obj.a = null;
crud(obj, 'a', null);
// aを確実に空にしつつ配列としてセット
crud(obj, 'a', {})('y', [])(0, 'first'); // { a: { y: ['first'] } }
高階関数面白い。