5

I have the following string:

const str = "prop1.prop2.prop3"

I want to use this string to access the property prop3 of the following object:

const obj = {
   prop1: {
      prop2:{
         prop3:{
            // ---- destination point
         }
      }
   }
}

But I'm not able to figure out how to do it? there must be something that keeps adding the obj[currentProp] so on and so on. and.. isn't there a quicker method? I'm afraid I'm wasting my time on something that can be achieved more easily

13
  • 1
    Does this answer your question? Dynamically updating a JavaScript object from a string path Commented Jul 10, 2022 at 12:44
  • 1
    This is a duplicate, but I can't find any of the old questions. You have to either write your own function or find one in a library. The language itself does not have a way to do this. Commented Jul 10, 2022 at 12:44
  • 1
    lodash for example has set and get which are quite handy Commented Jul 10, 2022 at 12:45
  • 1
    does this works for you mpath Commented Jul 10, 2022 at 12:49
  • 1
    @MohitSharma. yes that's, true. but I also want the community to benefit as well. by asking an abstract and straightforward question. not everyone is using React. If I'm a beginner and I was to read that question, I wouldn't understand the JSX part of the questions/answers. Commented Jul 10, 2022 at 13:00

4 Answers 4

20

This would be my approach:

const access = (path, object) => {
  return path.split('.').reduce((o, i) => o[i], object)
}

const obj = {
  prop1: {
    prop2: {
      prop3: {
        value: 'foo'
      }
    }
  }
}

const str = 'prop1.prop2.prop3'

console.log(access(str, obj)) // {"value": "foo"}
Sign up to request clarification or add additional context in comments.

1 Comment

aha, great then using array.reduce, I was thinking all the time of .map and .forEach
1

You can combine split with forEach as follows:

const str = "prop1.prop2.prop3"

const obj = {
   prop1: {
      prop2:{
         prop3:{
            a: "b",
            c: "d"
         }
      }
   }
}

var srch = obj;

str.split(".").forEach(item => (srch = srch[item]));

console.log(srch); // { a: "b", c: "d"}
console.log(obj);

split converts str's value into an array, which is then looped and on each iteration, srch gets one level deeper.

3 Comments

but that modifies the original obj in the memory because that's what var srch = obj exactly does
@Normal no, it does not. srch is a reference to a variable. If you say a = 1; b = 1; a = 2, that does not change b. Note that I did not change your elements of obj, I changed only the reference. I have edited my Fiddle to console.log(obj);. If you test it, you will see that srch is properly computed, while obj remained unchanged.
yes, you're right
0

different ways to access a nested property of an object

using a function accessDeepProp with two arguments the object and path of the nested property!

Recursive way:

function accessDeepProp(obj, path) {
  if (!path) return obj;
  const properties = path.split(".");
  return accessDeepProp(obj[properties.shift()], properties.join("."));
}

For-loop way:

function accessDeepProp(obj, path) {
  const properties = path.split(".");
  for (let i = 0; i < properties.length; i++) {
    if (!obj) return null;
    obj = obj[properties[i]];
  }
  return obj;
}

Eval way: never_use_eval!

function accessDeepProp(objName, path) {
  try {
    return eval(`${objName}.${path}`);
  } catch (e) {
    return null;
  }
}

you could also use lodash get method

Comments

-1

This is the shortest solution, and it supports arrays and ['bracket notation']. Just don't run it against malicious user input.

Update: a better(?) version without eval.

const obj = {
  prop1: {
    prop2: {
      prop3: {
        value: 'foo'
      }
    }
  }
}

const str = 'prop1.prop2.prop3'
//console.log(eval("obj." + str))

// a code without eval
var value = (Function("return obj." + str))();
console.log(value);

6 Comments

no, it will be downvoted with reason; since eval has risk if you use it just Never use eval()
Is using Function(body) considered a better option"?
It has similar problems, and in this case there's a simpler and safer solution.
if you add try catch it would be much safer! see my answer!
@Pointy Which lacks features vs the eval/Function version. I disagree to never use eval. If it's my data (and not arbitrary user data) I think it's ok to.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.