通过点语法字符串路径访问对象

时间:2012-02-18 03:14:35

标签: javascript

如何通过字符串myobject[path][to][obj]访问path.to.obj?我想调用一个函数Settings.write('path.to.setting', 'settingValue'),它会将'settingValue'写入settingObj[path][to][setting]。如果没有eval(),我怎么能这样做?

我终于在下面的一个用户回答它的同时想出来了。如果有兴趣的话,我会在这里发布我的文档,说明它是如何工作的。

(function(){
    var o = {}, c = window.Configure = {};

    c.write = function(p, d)
    {
        // Split the path to an array and assaign the object
        // to a local variable
        var ps = p.split('.'), co = o;

        // Iterate over the paths, skipping the last one
        for(var i = 0; i < ps.length - 1; i++)
        {
            // Grab the next path's value, creating an empty 
            // object if it does not exist
            co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
        }

        // Assign the value to the object's last path
        co[ps[ps.length - 1]] = d;
    }

    c.read = function(p)
    {
        var ps = p.split('.'), co = o;
        for(var i = 0; i < ps.length; i++)
        {
            co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
        }
        return co;
    }
})();

我遇到问题的原因是你必须跳过最后一条路。如果包含最后一个路径,则最终只能分配一个任意对象。

2 个答案:

答案 0 :(得分:3)

您可以使用str.split()

path = pathString.split('.');
settingObj[path[0]][path[1]][path[2]] = settingValue;

str.split()会将变量分成一个数组,并在指定字符的位置进行拆分。

这当然是操作的根源,并假设正确的输入。

修改:由于路径需要具有可变长度,因此这是根据您在上面显示的语法编辑的更新版本:

(function(){
    var o = {}, c = window.Configure = {};

    c.write = function(p, d)
    {
        var ps = p.split('.'), co = o;
        for(var i = 0; i < ps.length - 1; i++)
        {
            co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
        }
        co[ps[ps.length-1]] = d;
    }

    c.read = function(p)
    {
        var ps = p.split('.'), co = o;
        for(var i = 0; i < ps.length; i++)
        {
            co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
        }
        return co;
    }

    c.write('path.to.property', 'setting');
    alert(c.read('path.to.property'));
})();

答案 1 :(得分:2)

您的变量co包含对您的媒体资源的引用,但当您使用co更新co = p的值时,您只是覆盖了co的值,而不是财产的价值。您需要保留对最后一个键的引用,并使用该键设置值:

http://jsfiddle.net/gilly3/a2p8m/1/

c.write = function(p, d) 
{ 
    var ps = p.split('.'), co = o, key; 
    for(var i = 0; i < ps.length; i++) 
    { 
        if (key)
        {
            co = (key in co) ? co[key] : co[key] = {};
        }
        key = ps[i];
    } 
    co[key] = d; 
    console.log(co); 
    console.log(o); 
} 

您可能希望使用key in co而不是仅仅进行“真理”检查。否则,将保留1的值,而0的值将被{}覆盖。然后,这些值中的任何一个都会导致上述代码的运行时错误,因为您无法将属性写入数字。最好检查typeof co[key]

co = co[key] && /object|function/.test(typeof co[key]) ? co[key] : co[key] = {};

(我知道我的答案有点迟了,但是我想用大拇指打字后付出的努力,不管怎么说,不妨包括它)

我怀疑你遇到了分组错误。尝试将三元表达式中的结束符号移动到行尾:

co = (co[ps[i]] ? co[ps[i]] : co[ps[i]] = {});

我自己测试一下,但是我用手机回答,jsfiddle在用拇指打字时很乏味。