Dynamic deep selection for a JavaScript object

前端 未结 4 1074
伪装坚强ぢ
伪装坚强ぢ 2020-12-30 12:54

With a single property this is fairly easy:


var jsonobj = {
    \"test\": \"ok\"
}
var propname = \"test\";
// Will alert \"ok\"
alert(jsonobj[propname]);
<         


        
相关标签:
4条回答
  • 2020-12-30 13:36

    This works, but rather suckily uses eval so I'm not recommending it's use:

    var jsonobj = {
        "test": {
            "test2": "ok"
        }
    }
    var propname = "test.test2";
    alert(eval("jsonobj." + propname));
    ​
    

    Try it here: http://jsfiddle.net/TAgsU/

    0 讨论(0)
  • 2020-12-30 13:44
    function resolve(cur, ns) {
    
        var undef;
    
        ns = ns.split('.');
    
        while (cur && ns[0])
            cur = cur[ns.shift()] || undef;
    
        return cur;
    
    }
    

    E.g.

    // 1:
    resolve({
        foo: { bar: 123 }
    }, 'foo.bar'); // => 123
    
    
    // 2:
    var complex = {
        a: {
            b: [
                document.createElement('div')
            ]
        }
    };
    
    resolve(complex, 'a.b.0.nodeName'); // => DIV
    

    The benefit in using this is that it won't throw an error if you try accessing something that doesn't exist -- it'll gracefully return undefined.


    EDIT:

    In the comment, Andy mentioned that this doesn't throw errors where one might expect it to. I agree that getting undefined is a little bit generic and there is no way to tell whether your value was really resolved. So, to remedy that, try this:

    var resolve = (function(){
    
        var UNRESOLVED = resolve.UNRESOLVED = {};
        return resolve;
    
        function resolve(cur, ns) {
    
            var undef;
    
            ns = ns.split('.');
    
            while (cur && ns[0])
                cur = cur[ns.shift()] || undef;
    
            if (cur === undef || ns[0]) {
                return UNRESOLVED;
            }
    
            return cur;
    
        }
    
    }());
    

    It'll return an UNRESOLVED object that can be checked like so:

    var result = resolve(someObject, 'a.b.c');
    
    if (result === resolve.UNRESOLVED) {...}
    

    It's not perfect, but it is (IMO) the best way to determine an unresolved namespace without having to throw errors. If you want errors, then just go ahead with:

    someObject.a.b.c; //...
    
    0 讨论(0)
  • 2020-12-30 13:46

    You can write a little function to split the string and then access each piece in turn. For example:

    function getProperty(propname, object)
    {
        var props = propname.split('.');
        var obj = object;
        for (var i=0; i<props.length; i++)
        {
           obj = obj[props[i]];
        }
        return obj;
    }
    

    Obviously it nees a little extra coding to check for null objects, valid properties, etc.

    0 讨论(0)
  • 2020-12-30 13:48

    I also just implemented this using an inner recursive function like so:

    function get(obj, ns) {            
    
        function recurse(o, props) {
            if (props.length === 0) {
                return o;
            }
            if (!o) {
                return undefined;
            }
            return recurse(o[props.shift()], props);
        }
    
        return recurse(obj, ns.split('.'));
    }
    

    This will return the deep value of the property specified by the ns param, otherwise will always return undefined if it doesn't exist or there are any problems along the way.

    0 讨论(0)
提交回复
热议问题