0

My goal is this:

Say if I have a reference

a: {
    b: {
        c:{
           d: {
                  //Some properties here. 
           }
        } 
    }
}

Then by using a string like "a.b.c.d" (which is not known in advance), I want to be able to transverse the object and get the value of d (or return null / throw Error).

I am aware that we can always get the value for one depth below (for example a["b"] and so on) and then this can definitely be achieved using the.split() and then use loops or recursion, but I was hoping there was a simpler, one step method of doing so.

Divyansh Goenka
  • 997
  • 2
  • 12
  • 35

3 Answers3

1

There is not other way to do that without using loops are recursion. eval() can do that but its not recommended.

const getProp = (obj,path) => path.split('.').reduce((ac,a) => (ac || {})[a],obj);

const obj = { a: {
    b: {
        c:{
           d: {
              someprop:"x"
           }
        } 
    }
}
}
console.log(getProp(obj,"a.b.c.d"))

Another way could be using Proxy() but I would still say reduce() is better.

const obj = { 
    a: {
        b: {
            c:{
               d: {
                  someprop:"x"
               }
            } 
        }
    }
}

const handler = {
  get:function(obj,prop){
    if(prop.includes('.')) return prop.split('.').reduce((ac,a) => (ac || {})[a] ,obj)
    else return obj[prop]
  }
}

let res = new Proxy(obj,handler);

console.log(res['a.b.c.d'])

Bases on the comment "a.b.c.d is not known in advance".

const obj = { 
    a: {
        b: {
            c:{
               d: {
                  someprop:"x"
               }
            } 
        }
    }
}
const getProp = (obj,depth) => [...Array(depth)].reduce((ac,a) => (Object.values(ac)[0] || {}),obj)

console.log(getProp(obj,4))
Maheer Ali
  • 35,834
  • 5
  • 42
  • 73
0

Yes there is a simple solution, put the string inside eval and put the eval inside try/catch

const a = {b:{c:{d:"test"}}};
try{
  console.log(eval("a.b.c.d")); // test
}catch(e){}
Bilal Alam
  • 874
  • 10
  • 26
0

As you mentioned that, the keys are not known in advance then recursion or a loop would be the way to go:

Then by using a string like "a.b.c.d" (which is not known in advance), I want to be able to transverse the object and get the value of d (or return null / throw Error).

const object = { 
    a: {
        b: {
            c:{
               d: {
                   foo : "bar"
               }
            } 
        }
    }
};

function getNestedData(obj){
 if(!obj){
  return null;
 }
 if(Object.values(obj).filter(val => typeof val !== "object").length){
  return (Object.values(obj)[0] || {});
 }
  return getNestedData(Object.values(obj)[0] || {});
}
console.log(getNestedData(object));
Fullstack Guy
  • 16,368
  • 3
  • 29
  • 44