2

Given the following obj:

var inputMapping = {
 nonNestedItem: "someItem here",
 sections: {
   general: "Some general section information" 
 }
};

I'm writing a function to get that data by passing in a string "nonNestedItem" or in the nested case "sections.general". I'm having to use an eval and I was wondering if there was maybe a better way to do this.

Here is what I have so far and it works okay. But improve!

function getNode(name) {
  var n = name.split(".");

  if (n.length === 1) { 
   n = name[0];
  } else { 
    var isValid = true,
        evalStr = 'inputMapping';

    for (var i=0;i<n.length;i++) { 
      evalStr += '["'+ n[i] +'"]';

      if (eval(evalStr) === undefined) {
        isValid = false;
        break;
      }
    }

    if (isValid) { 
      // Do something like return the value 
    }
  }
}

Linky to Jsbin

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
Mike Fielden
  • 10,055
  • 14
  • 59
  • 99
  • 1
    There's no JSON here. Don't confuse JavaScript objects with JSON. – Quentin Jan 13 '14 at 16:22
  • possible duplicate of [JavaScript object: access variable property by name as string](http://stackoverflow.com/questions/4255472/javascript-object-access-variable-property-by-name-as-string) – Quentin Jan 13 '14 at 16:22
  • Calm down. Ok its a js object i will remove all references to `json`. A bit nitpicky though. I dont think this is a dupe of that question. – Mike Fielden Jan 13 '14 at 16:29

2 Answers2

5

You can use Array.prototype.reduce function like this

var accessString = "sections.general";

console.log(accessString.split(".").reduce(function(previous, current) {
    return previous[current];
}, inputMapping));

Output

Some general section information

If your environment doesn't support reduce, you can use this recursive version

function getNestedItem(currentObject, listOfKeys) {
    if (listOfKeys.length === 0 || !currentObject) {
        return currentObject;
    }
    return getNestedItem(currentObject[listOfKeys[0]], listOfKeys.slice(1));
}
console.log(getNestedItem(inputMapping, "sections.general".split(".")));
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
2

You don't need to use eval() here. You can just use [] to get values from an object. Use a temp object to hold the current value, then update it each time you need the next key.

function getNode(mapping, name) {
    var n = name.split(".");

    if (n.length === 1) {
        return mapping[name];
    } else {
        var tmp = mapping;
        for (var i = 0; i < n.length; i++) {
            tmp = tmp[n[i]];
        }
        return tmp;
    }
}
gen_Eric
  • 223,194
  • 41
  • 299
  • 337