lodashのcloneDeepWithはコールバックを適用してオブジェクト/配列をディープコピーするという関数ですが、ディープコピーの際に「オブジェクト/配列の全要素にアクセスする」という特性を利用して抽出や加工を行うことができます。
階層が固定の場合はネイティブでもfilterやmap、findなど有用な関数がありますが、階層が不定の場合は自前で再帰関数を書くなどちょっとややこしくなります。そういった場合にcloneDeepWithを使えば手っ取り早くオブジェクト/配列の操作を行うことができます。
ADs
以下のようなオブジェクトがあったとして
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
var obj = { item: { id: 1, name: '親です', key: 'parent', flg: true, children: [{ item: { id: 2, name: '子その1', key: 'child1', flg: false, }, item: { id: 3, name: '子その2', key: 'child2', flg: true, children: [{ item: { id: 4, name: '孫その1', key: 'child4', flg: false, }, item: { id: 5, name: '孫その2', key: 'child5', flg: true, } }] } }] } } |
いくつか処理をやってみます。
gettrueObjにflgがtrueのidを格納します。
1 2 3 4 5 6 7 8 |
var gettrueObj = [] _.cloneDeepWith(obj, function (val) { if (typeof val.flg !== 'undefined') { if (val.flg === true) { gettrueObj.push(val.id) } } }) |
すべての要素にcheck:falseというkey/valueを足します。
(ここではidを持っている要素を対象とすることで、itemオブジェクト配下にcheckというキーを足しています)
1 2 3 4 5 |
var addcheckObj = _.cloneDeepWith(obj, function (val) { if (typeof val.id !== 'undefined') { val.check = false; } }) |
item.childrenが子要素となっていますが、この子要素を持っていないitemを抽出します。
1 2 3 4 5 6 7 8 |
var notchildObj = [] _.cloneDeepWith(obj, function (val, key) { if (key == 'item') { if (typeof val.children === 'undefined') { notchildObj.push(val); } } }) |
id以外(正確にはidとchildrenオブジェクト)のvalueをfalseとします。
1 2 3 4 5 6 |
var setfalseObj = _.cloneDeepWith(obj, function (val, key) { if (key !== 'id' && (_.isString(val) || _.isBoolean(val))) { val = false; return val; } }) |
実際にどういう値になるかはこちらをご参照ください
_.cloneDeepWithはその名前からオブジェクト/配列の複製にしか使わなさそうな関数と思いがちですが、lodashの持つほとんどの関数は_.cloneDeepWithで代替できるほどに強力です。
もちろん負荷や速度とのトレードオフにはなりますが、困ったときの選択肢の一つとして検討してみてください。
ADs
コメントはまだありません。