【问题标题】:access object through dot-syntax string path通过点语法字符串路径访问对象
【发布时间】:2012-02-18 03:14:34
【问题描述】:

如何通过字符串path.to.obj 访问myobject[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;
    }
})();

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

【问题讨论】:

    标签: javascript


    【解决方案1】:

    您可以为此使用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'));
    })();
    

    【讨论】:

    • 但你永远不知道路径有多少部分。可能是 2,可能是 6。
    • 我的错,我认为这是某种预先存在的设置或其他东西。我把代码放在这里:jsfiddle.net/HVh7X,我在看到你的编辑之前就开始了,所以我会在一分钟内更新我的答案。
    • 大声笑,是的,刚刚想通了。我需要跳过最后一条路径,因为我只是分配了一个任意值。一旦你编辑你的答案,我会接受它。
    • 警告,你上面的代码会覆盖任何对象,即使你试图追加它。第 9 行和第 10 行应更改为 co = (co[ps[i]])? co[ps[i]] : co[ps[i]] = {};
    • 好点。我没有想到预先存在的设置路径。已编辑,现在应该可以了。无论如何,感谢您将其标记为答案。 :)
    【解决方案2】:

    您的变量co 包含对您的属性的引用,但是当您使用co = p 更新co 的值时,您只是覆盖了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 仅用拇指打字时很乏味。

    【讨论】:

      猜你喜欢
      • 2011-09-23
      • 2019-06-30
      • 1970-01-01
      相关资源
      最近更新 更多