JavaScript在不知道级别的情况下为嵌套对象中的元素赋值

时间:2013-05-14 00:42:02

标签: javascript object

说我有这样一个对象:

a : {
  a1 : {
    a2: true
  } 
}

我将所有路径保存在数组中:

[a1, a2]

如果我想为[“a1”] [“a2”]赋值,很容易:

a["a1"]["a2"] = true;

但是当我有这样的3级路径时:

[a1, a2, a3]

我必须手动编写如下代码:

a["a1"]["a2"]["a3"] = true;

有没有办法自动处理任何级别的路径,这样我就不必为每一个案例明确说明?

请注意,“a”可能非常复杂,因此我只想为此特定元素指定值而不触及其余元素。

5 个答案:

答案 0 :(得分:5)

您可以使用如下路径迭代遍历对象:

function setDeepProperty(obj, path, value)
{
    var curr = obj;

    for (var depth = 0; depth < path.length - 1; depth++)
    {
        curr = curr[path[depth]];
    }

    curr[path[path.length - 1]] = value;
}

这假定路径有效。如有必要,请确保path[depth] in curr。遍历的最后一步是在循环之外完成的,因为它将curr设置为基本类型而不是引用数组(如我们所愿),这意味着它不会更改原始数据。然后,按照你的例子:

var arr = {a1: {a2: { a3: false }}};
setDeepProperty(arr, ["a1", "a2", "a3"], true);

请注意,路径中的节点是字符串。

答案 1 :(得分:3)

您可以通过多种方式访问​​这些属性:

使用循环:

var obj = {
        a1 : {
            a2: { a3: 'test' }
        } 
    },
    i = 0,
    keyPath = ['a1', 'a2', 'a3'],
    len = keyPath.length;

    for (; i < len; i++) {
        obj = obj[keyPath[i]];
    }

    console.log(obj);

使用eval(我不建议这样做):

var obj = {
            a1 : {
                a2: { a3: 'test' }
            } 
        };

var value = eval('obj.' + keyPath.join('.'));

console.log(value);

您可以使用相同的方法在特定关键路径设置属性:

function setProperty(obj, keyPath, value) {
    var i = 0,
        len = keyPath.length - 1;

    for (; i < len; i++) {
        obj = obj[keyPath[i]];
    }

    obj[keyPath[i]] = value;
}

答案 2 :(得分:1)

所有这些都是优雅的解决方案,我的2美分递归: -

Test Here

var a = {
    a1: {
        a2: {
            a3: false
        }
    }
};

var path = ['a1', 'a2', 'a3'];

var valueToSet = true;
setValue(0, a);


function setValue(level, ob) {
  var prop = path[level];

  if (!ob.hasOwnProperty(prop)) {
    return;
  }
   if (level == (path.length - 1)) {
    ob[prop] = valueToSet;
    return;
   }

   return setValue(level + 1, ob[prop]);

}
console.log(a);

答案 3 :(得分:0)

您有两种可能性:

  • 可怕的eval()。我拒绝为此提供代码
  • 进出循环:

代码:

var a={
  a1 : {
    a2 : {
      a3: false
    } 
  } 
};
var idx=["a1", "a2", "a3"];

function recReplace(o, i, v) {
  var ii=i.shift();
  if (i.length==0)
    o[ii]=v;
  else
   o[ii]=recReplace(o[ii],i,v);
  return o;
}

b=recReplace(a,idx,true); //or: a=recReplace(a,idx,true);

答案 4 :(得分:0)

当然,这是一个简单的循环:

var a = {a1:{a2:{}}};

var path = ["a1", "a2", "a3"];
for (var o=a, i=0; i<path.length-1; i++)
    o = o[path[i]]; // notice that this will throw exception
                    // when the objects do not exist already
o[path[i]] = true;