Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have a nested Javascript object like

var data = { 'name':    { 'heading': 'Name', 'required': 1, 'type': 'String' },
             'profile': {
                  'age':   { 'heading': 'Age', 'required': 0, 'type': 'Number' },
                  'phone': { 'heading': 'Phone', 'required': 0, 'type': 'String'},
                  'city':  { 'heading': 'City', 'required': 0, 'type': 'String'},
                  },
             'status':  { 'heading': 'Status', 'required': 1, 'type': 'String' }
           };

Here, I can access the fields as data.profile.age.type or data.name.type. No Issues And if I have dynamic variable names, I can access as below. Again, No Problems.

f = 'profile'; data[f].age.type

But, here I have variable names like 'name', 'profile.age', 'profile.city' etc and obviously I cannot access them as f = 'profile.age'; data[f].type which will not work.

Can anyone guide me how to access them (get/set) in the most straight-forward and simple way?

Note: I tried this and it works for get.

data.get = function(p) { o = this; return eval('o.'+p); };
f = 'profile.age'; data.get(f).name;

though set does not seem to be simple enough. Please let me know, if there are better solutions for get and set as well.

share|improve this question
1  
You were right to ask this question on SO. Anytime you find yourself using eval in Javascript, you are almost certainly doing the wrong thing. –  Bobby Eickhoff Dec 13 '10 at 17:40
 
Thanks for letting me know about eval. May be eval is evil! :-) –  rsmoorthy Dec 13 '10 at 17:53
 
You said it. Take a look at the last suggestion offered here: javascript.crockford.com/code.html –  Bobby Eickhoff Dec 13 '10 at 18:26

3 Answers

up vote 4 down vote accepted

Don't use eval unless absolutely necessary. :) At least in this case, there are better ways to do it -- you can split the nested name into individual parts and iterate over them:

data.get = function(p) {
  var obj = this;

  p = p.split('.');
  for (var i = 0, len = p.length; i < len - 1; i++)
    obj = obj[p[i]];

  return obj[p[len - 1]];
};

data.set = function(p, value) {
  var obj = this;

  p = p.split('.');
  for (var i = 0, len = p.length; i < len - 1; i++)
    obj = obj[p[i]];

  obj[p[len - 1]] = value;
};
share|improve this answer
 
Thanks. Very fast response and helpful. –  rsmoorthy Dec 13 '10 at 17:51

You can just nest the brackets:

var a = 'name', b = 'heading';
data[a][b]; // = `Name`
share|improve this answer
1  
this is not answering the question at all... –  vsync Sep 21 '11 at 11:53
1  
@vsync: Sure it does. I'm saying that rather than var a='name.heading'; data[a], you can use successive sets of brackets to access deeper levels of the object. So if you know you're looking for something in the profile object, var a='profile',b='age'; data[a][b] works. Obviously, if you need to handle an arbitrary string, the other answers show how to do that. This is an alternative if someone doesn't need the complexity of parsing arbitrary "a.b.c.d" strings. –  josh3736 Sep 21 '11 at 14:43

Perhaps a function that takes in the path to the property you're interested in and breaks it up into tokens representing properties. Something like this (this is very rough, of course):

data.get = function(path) {
  var tokens = path.split('.'), val = this[tokens[0]];
  if (tokens.length < 2) return val;
  for(var i = 1; i < tokens.length; i++) {
     val = val[tokens[i]];
  }
  return val;
}

example:

   var f = 'one.two';
   var data = { one: {two:'hello'}};
   data.get = /* same as above */;

   var val = data.get(f);
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.