Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/backbone.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript对象的动态深度选择_Javascript_Object_Properties - Fatal编程技术网

JavaScript对象的动态深度选择

JavaScript对象的动态深度选择,javascript,object,properties,Javascript,Object,Properties,对于单个属性,这相当容易: var jsonobj = { "test": "ok" } var propname = "test"; // Will alert "ok" alert(jsonobj[propname]); 但我要做的是使用嵌套属性: var jsonobj = { "test": { "test2": "ok" } } var propname = "test.test2"; // Alerts undefined alert(j

对于单个属性,这相当容易:


var jsonobj = {
    "test": "ok"
}
var propname = "test";
// Will alert "ok"
alert(jsonobj[propname]);
但我要做的是使用嵌套属性:


var jsonobj = {
    "test": {
        "test2": "ok"
    }
}
var propname = "test.test2";
// Alerts undefined
alert(jsonobj[propname]);
有没有办法选择嵌套的“动态”属性?
我知道我可以做jsonobj.test.test2,但问题是propname可以更改为深度为1、2或3级的属性。(例如test,test.test2,…)

这是可行的,但它使用的是
eval
,所以我不建议使用它:

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

在这里试试:

您可以编写一个小函数来拆分字符串,然后依次访问每个片段。例如:

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;
}
函数getProperty(propname,object)
{
var props=propname.split('.');
var obj=对象;
对于(var i=0;i
例如

使用它的好处是,如果您尝试访问不存在的东西,它不会抛出错误——它将优雅地返回未定义的


编辑:

在评论中,Andy提到,这不会在人们可能期望的情况下引发错误。我同意,获取
未定义的
有点通用,无法判断您的值是否真的得到了解决。因此,要纠正这一点,请尝试以下方法:

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;

    }

}());
它将返回一个未解析的对象,可以这样检查:

var result = resolve(someObject, 'a.b.c');

if (result === resolve.UNRESOLVED) {...}
它并不完美,但它是(IMO)确定未解析命名空间而不必抛出错误的最佳方法。如果您想要错误,请继续执行以下操作:

someObject.a.b.c; //...

我还使用一个内部递归函数实现了这一点,如下所示:

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('.'));
}

这将返回ns参数指定的属性的深度值,否则,如果该属性不存在或在访问过程中出现任何问题,则将始终返回undefined。

如果尝试访问空/未定义值的属性,则仍然会出现TypeError。……除了上述可能导致的其他灾难之外,这就是我不推荐它;)不得不说,我非常喜欢这样做。+1这样做的主要缺点是没有错误控制。如果我在节点路径中键入错误,将返回未定义的
,而您一点也不知道。这类似于使用PHP的
@
操作符来达到相同的目的。@Andy,这是解决方案的本质。如果您想要错误,为什么不使用常规的呢查找(
obj.a.b.c
)?无论如何,我已经用一种可能的补救方法编辑了答案。@J-P:这个问题要求一个接受动态级别数的解决方案。没有提到错误控制。但是,我可以看到某些情况下错误控制是没有用的,例如,在返回JSON深度可变的web服务中-我与thos合作过e before(易趣API浮现在脑海中)。您不必递归地检查某些内容是否存在,您可以在此处使用您的方法并检查未定义的内容,忽略它并继续。如果属性值为“falsy”,即0或false或“”或null,则此代码不会返回未定义的内容吗?这可能(也可能不是)你指的是JSON还是JavaScript对象?它们不一样。请注意,递归方法虽然更漂亮,但比迭代方法慢(至少在我的测试中)
someObject.a.b.c; //...
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('.'));
}