the code below is an object from database
{
"id_": "1",
"name": "Enemy x",
"image": "image.png",
"stats": {
"level": 1,
"attack": 5,
"defense": 0
}
}
And need edit attack or defense, but with a "pointer" saved in a constant, All this in a dynamic way since the value to edit could be in a third or fourth level of the object. for example:
const edit = 'stats/attack';
// const edit = 'stats/other/example'; <- example
I have some ideas but I don't know if exist best practices for this, or how to look for it on the internet since I can't find anything like it.
use a reduce:
const data =
{ id_ : '1'
, name : 'Enemy x'
, image : 'image.png'
, stats:
{ level : 1
, attack : 5
, defense : 0
} }
function getVal( obj, key )
{
return key.split('/').reduce((o,v)=>o[v],obj)
}
console.log('--> ', getVal( data, 'stats/attack' ))
In case of a wrong path:
const data =
{ id_ : '1'
, name : 'Enemy x'
, image : 'image.png'
, stats:
{ level : 1
, attack : 5
, defense : 0
} }
const getVal = ( obj, path ) =>
path.split('/').reduce((o,v)=> o?.[v] ,obj) // better than `o[v] ?? 'error!`'
console.log('1-->', getVal( data, 'stats/attack' )) // --> 5
console.log('2-->', getVal( data, 'stats/xxx' )) // --> undefined
console.log('3-->', getVal( data, 'zzz/xxx' )) // --> undefined
console.log('4-->', getVal( data, '' )) // --> undefined
// thanks to pilchard comment
console.log('5-->', getVal( data, 'stats/xxx/1' )) // --> undefined
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}
PO : if I want to change it to 10. I will test to see if I can do it with this method
maybe that ?
usage 1 : get the value
let val = onElm( data, 'stats/attack' )
usage 2 : change the value (to 10)
let val = onElm( data, 'stats/attack', 10 )
Demo;
const data =
{ id_ : '1'
, name : 'Enemy x'
, image : 'image.png'
, stats:
{ level : 1
, attack : 5
, defense : 0
} }
const onElm = ( obj, path, newVal=null ) =>
path.split('/').reduce((o,p,i,{length:n}) =>
(++i<n) ? o[p] : newVal ? o[p] = newVal : o[p], obj)
console.log('get value of "stats/attack"\n return value ->'
, onElm( data, 'stats/attack' ) ) // return value -> 5
console.log('change value of "stats/attack to 10"\n return value ->'
, onElm( data, 'stats/attack', 10) ) // return value -> 10
console.log ( '\nverify data Object now with new value: \n', data )
.as-console-wrapper {max-height: 100% !important;top: 0;}
.as-console-row::after {display: none !important;}
You can use lodash zipObjectDeep to achieve that but path works via '.', so you need to
const edit = 'stats/attack';
const path = edit.split('/').join('.')
zipObjectDeep([path], [1]);
Replace all / with . then eval the string that represents obj.this.that.
Bonus: This works for arrays too "stats/level[2]/other"
var obj = {
"id_": "1",
"name": "Enemy x",
"image": "image.png",
"stats": {
"level": 1,
"attack": 5,
"defense": 0
}
};
var path = "stats/level";
var value = (eval ("obj." + path.replace(/\//g, ".")));
console.log(value)