1

说我有一个这样的对象:

a : {
  a1 : {
    a2: true
  } 
}

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

[a1, a2]

如果我想给 a["a1"]["a2"] 赋值,很简单:

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

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

[a1, a2, a3]

我必须手动编写这样的代码:

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

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

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

4

5 回答 5

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);

这里注意路径中的节点是字符串。

于 2013-05-14T00:56:48.793 回答
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;
}
于 2013-05-14T00:54:49.763 回答
1

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

在这里测试

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);
于 2013-05-14T01:03:35.253 回答
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);
于 2013-05-14T00:54:03.033 回答
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;
于 2013-05-14T00:55:34.000 回答