0

Eval seems to be generally regarded as a bad idea.

Is there an elegant solution to an eval on nested objects.

So my eval is

eval( "$scope" + lookup_string) 

As Javascript opbjects seem to be assoiative arrays, I tried

$scope[lookup_string] 

This worked fine until I got to some nested objects.

so if my string contains dots, e.g

lookup_string = "object1.object2.object3"

This works as an eval. But not as an associative_array lookup, as it is treating the string as one, not as three nested lookups.

Now I know I can split the string, and lookup each part, but this seems a fair bit work (compared to eval-ing the string).

Are there any other clean / elegant alternatives to this?

wobbily_col
  • 11,390
  • 12
  • 62
  • 86
  • possible duplicate of [Convert Javascript string in dot notation into an object reference](http://stackoverflow.com/questions/6393943/convert-javascript-string-in-dot-notation-into-an-object-reference) – Quentin Sep 02 '13 at 11:14
  • Ok, different question, but same answer at the end of the day. Though if there are other alternatives, I would like to see them. – wobbily_col Sep 02 '13 at 11:25

2 Answers2

3

Simple while loop is usually enough for this problem.

function nameSpace(obj, path) {
  var property, 
      path = path.split('.');
  while (property = path.shift()) {
    if (typeof obj[property] === 'undefined')
      return undefined;
    obj = obj[property]
  }
  return obj
}

UPDATE

Well if you just want to use vanilla AND you are certain that the environment you are developing in supports ECMA-5, you can do something like this

function namespace(object, path) {
   var result = path.split('.').reduce(function (value, index) {
        return value[index]
    }, object)
   return result;
}
console.log(namespace(obj, 'a.b.value'))

You could also use a library like lodash to add reduce if it's not natively implemented.

arb
  • 7,753
  • 7
  • 31
  • 66
  • That's ten lines compared to one eval line. Having looked up the reasons for eval being bad (security, debugging, speed), as this is an internal app, I don't see using eval being such a problem, if this is the alternative. – wobbily_col Sep 02 '13 at 12:46
1

This one works with array items:

var oTest = {
    "mypc": {
        "cpu": {
            "cores": 1,
                "manufacturer": "",
                "model": "",
                "speed": 0
        },
            "group": "",
            "hdds": [{
            "capacitygb": 0,
                "driveletter": "c",
                "hddid": "a18822e92ff6e14cbc905bf4df13f8d3",
                "manufacturer": "",
                "port": 0,
                "type": ""
        }]
    }
};


var getProperty = function (obj, path) {
    return path.split(/(\[|\]|\.)/).reduce(function (x, y) {
        return ('[].'.indexOf(y) > -1) ? x : (x === Object(x) && y in x) ? x[y] : undefined;
    }, obj)
}

console.log(oTest.mypc.hdds[0].hddid)
console.log( 'ok: '+ getProperty(oTest, 'mypc.hdds[0].hddid')) 
console.log( 'undefined path: '+ getProperty(oTest, 'mypc.hdds[10].hddid')) 
Marco Plaza
  • 319
  • 1
  • 5