1

Possible Duplicate:
Accessing nested JavaScript objects with string key

I have the function

function _get(name) {
return plugin._optionsObj[name] !== undefined ? 
    plugin._optionsObj[name] : plugin._defaults[name];
}

I would like to be able to have objects inside of my _defaults object, but then I don't know how to retrieve them but using just one set of square brackets.

i.e.

plugin._defaults = {
    val1: 1,
    val2: 2,
    obj1: {
        someVal: 3
    }
}

Is it possible to access 'someVal' from the function I have above? I tried passing 'obj1.someVal' for the argument and it didn't work. Ideas?

Edit: I have found a solution and I posted it below as an answer. I've written a very nice little function to do go through the nested values with a string and I didn't have to change my function much to implement it. I hope this helps anyone in a similar situation.

Community
  • 1
  • 1
Klik
  • 1,757
  • 1
  • 21
  • 38
  • return plugin._optionsObj[name] !== undefined ? plugin._optionsObj[name] : plugin._defaults[obj1][someVal]; doesn't work? – lelloman Feb 02 '13 at 23:32
  • 1
    See this gist: https://gist.github.com/3208381#file__.deep.js... If you use Underscore, you just pass the path (e.g. 'obj1.someVal') as a string, and it traverses the object graph to find the nested value. – Vlad Magdalin Feb 02 '13 at 23:34
  • I'm looking to see if there is a way to solve this without changing my function or implementation of it. – Klik Feb 02 '13 at 23:39
  • @VladMagdalin can you make an example? I'm not sure what you mean about using the underscore. – Klik Feb 02 '13 at 23:42
  • Without changing your _get() function, no it's not possible to solve this, unless you can change the structure of your data. [Underscore](http://underscorejs.org/) is a library (similar to jQuery) that helps you work with JavaScript objects. The _.deep() mixin I posted is a plugin for Underscore. – Vlad Magdalin Feb 02 '13 at 23:42
  • @TheWeirdNerd have a try with my answer! the example function works so yours should work too – lelloman Feb 02 '13 at 23:51
  • @VladMagdalin That answer is actually pretty helpful, though not 100% what I'm looking for. I've written my own answer already, but I think that code is pretty useful. Thanks. Upvote :). – Klik Feb 03 '13 at 00:42
  • Why not just use `_get("obj1").someVal`? – Bergi Feb 03 '13 at 12:39
  • @Bergi I've since solved the problem. Since you commented though, the purpose of my function is to first check to see if the nested object or value exists, and if not, to default. If I do what you suggest, I will not be defaulting because the object may exist in both the user defined and defaults, but the value may not. It defeats the purpose of my function. – Klik Feb 06 '13 at 00:55

4 Answers4

1

I suspect that you won't always have a one-level nested object to access, so the cleaner way to do this is to use a function that traverses an object based on a string path. Here's one that is coded as a mixin for Underscore. You can then just use it like so:

_.deep(plugin._defaults, 'obj1.someVal');

This thread also has some non-Underscore alternatives.

Community
  • 1
  • 1
Vlad Magdalin
  • 1,692
  • 14
  • 17
0

Pass multiple arguments, and iterate over the arguments object.

function _get(/* name1, name2, namen */) {
    var item = plugin._optionsObj,
        defItem = plugin._defaults;

    for (var i = 0; i < arguments.length; i++) {
        item = item[arguments[i]];
        defItem = defItem[arguments[i]];

        if (item == null || defItem == null)
            break;
    }
    return item == null ? defItem : item;
}

var opt = _get("obj1", "someVal")
the system
  • 9,244
  • 40
  • 46
0

I found a solution for this problem, at least one that will accommodate myself, and I'd like to share it in case it can help someone else with this problem. My biggest difficulty is that I did not know the depth of the nested value so I wanted to find a solution that would work for deeply nested objects and without requiring to redesign anything.

/* Retrieve the nested object value by using a string. 
   The string should be formatted by separating the properties with a period.
   @param   obj             object to pass to the function
            propertyStr     string containing properties separated by periods
   @return  nested object value. Note: may also return an object */

function _nestedObjVal(obj, propertyStr) {
var properties = propertyStr.split('.');
if (properties.length > 1) {
    var otherProperties = propertyStr.slice(properties[0].length+1);    //separate the other properties
        return _nestedObjVal(obj[properties[0]], otherProperties);  //continue until there are no more periods in the string
} else {
    return obj[propertyStr];
}
}


function _get(name) {
    if (name.indexOf('.') !== -1) {
    //name contains nested object
        var userDefined = _nestedObjVal(plugin._optionsObj, name);
        return userDefined !== undefined ? userDefined : _nestedObjVal(plugin._defaults, name);
    } else {
        return plugin._optionsObj[name] !== undefined ?
        plugin._optionsObj[name] : plugin._defaults[name];
    }
}
Klik
  • 1,757
  • 1
  • 21
  • 38
-1

To retrieve objects inside of your _defaults object you'll need to improve your _get function.

For example you may pass an array of strings (each string representing a propery name) to _get to allow access to deeply nested objects.

Paolo
  • 15,233
  • 27
  • 70
  • 91