0

I'm finding myself struggling with a little problem. Let's say I've got an object:

var foo = {
    bar: {
        baz: true
    }
};

Now I also have a String 'foo.bar.baz'. I'd now like to retrieve the value from the object using the string.

Please note: This is just an example, the solution needs to be dynamic.

Update:

I need the variable name also to be dynamic and parsed from the string. Also I can't be sure that my variable is a property of the window.

I have already built a solution using eval, but this is pretty ugly I think: http://jsfiddle.net/vvzyX/

Julian Hollmann
  • 2,902
  • 2
  • 25
  • 44

4 Answers4

4

For example,

function get(obj, path) {
    return path.split('.').reduce(function(obj, p) {
        return obj[p]
    }, obj);
}

Demo:

tree = {
    foo: {
        bar: 1,
        baz: { quux: 3 },
    },
    spam: 1
}

console.log(get(tree, 'foo.baz.quux')) // 3
georg
  • 211,518
  • 52
  • 313
  • 390
2

Here is how you can do this:

function getValue(namespace, parent) {
    var parts = namespace.split('.'),
        current = parent || window;
    for (var i = 0; i < parts.length; i += 1) {
        if (current[parts[i]]) {
            current = current[parts[i]];
        } else {
          if (i >= parts.length - 1)
            return undefined;
        }
    }
    return current;
}
var foo = {
    bar: {
        baz: true
    }
};
console.log(getValue('foo.bar.baz')); //true

The first argument of the function is the namespace (dot separated values) and the second one is the parent object, if parent is not provided then window is used.

One more example using the parent argument:

var str = 'foo.bar.baz';
    foo = {
       bar: {
          baz: true
       }
    };

result = getValue(str, foo);
console.log(result);

Here is an example in jsfiddle.

Similar approach is used in YUI. Their approach is called Namespace pattern. The main benefit is simulation of packages/namespaces. The only difference between this script and the namespace pattern is that the namespace function creates nested structure instead of only returning value.

Minko Gechev
  • 25,304
  • 9
  • 61
  • 68
2

Try this:

var name = [window].concat('foo.bar.baz'.split('.')).reduce(function(prev, curr) {
    return prev[curr];
});

console.log(name);

// -> 'true'
Amberlamps
  • 39,180
  • 5
  • 43
  • 53
  • interesting but I cannot get it to work properly, somehow prev[curr] is not accepted: http://jsfiddle.net/VXeaa/ – primavera133 Jul 31 '13 at 09:29
  • You are not using my original code. You missed `[window].concat([...])` in your code example. – Amberlamps Jul 31 '13 at 10:30
  • This is copy-pasted from your example, still no good in Chrome: http://jsfiddle.net/VXeaa/2/ – primavera133 Jul 31 '13 at 12:40
  • JsFiddle runs its code in a local scope, therefore `foo` is not global. As a result `window["foo"]` is undefined. This code only works if your object is globally accessible. – Amberlamps Jul 31 '13 at 12:59
0

What I can think of is using string split to split that string into an array first, and access the object via [] to access the attribute of that object with a loop

Simon Wang
  • 2,843
  • 1
  • 16
  • 32