Javascript:通过将路径作为字符串传递给对象来从对象中获取深层值

IT技术 javascript syntax path
2021-01-15 08:30:35

可能的重复:
使用字符串键访问嵌套的 JavaScript 对象

也许标题不够清楚,我只是不知道如何指定我要找的东西,而且我的英语真的很糟糕,抱歉。

我正在尝试创建返回对象值的函数,但也可以很好地处理嵌套对象。例如:

var obj = {
  foo: { bar: 'baz' }
};

我想通过向函数提供字符串“foo.bar”来访问 obj.foo.bar 的值。

function(obj, path) {
  // Path can be "foo.bar", or just "foo".
}

谢谢!

5个回答

这正常工作:

var deep_value = function(obj, path){
    for (var i=0, path=path.split('.'), len=path.length; i<len; i++){
        obj = obj[path[i]];
    };
    return obj;
};

这是证明/演示:jsfiddle.net/tadeck/5Pt2q/13/

编辑:我删除了冗余变量,缩短了代码。

我认为检查一下会更安全 obj[path[i]] === undefined
2021-03-22 08:30:35
改变参数是不好的做法。
2021-03-24 08:30:35
@SteveBlack 更好怎么办?它支持更受限制的语法,并且在尝试解析不存在的密钥时没有错误检查。
2021-03-25 08:30:35
2021-03-30 08:30:35
ES6 相同: const deep_value = (o, p) => p.split('.').reduce((a, v) => a[v], o);
2021-04-08 08:30:35

考虑一下:

var obj = {
  foo: { bar: 'baz' }
};

function deepFind(obj, path) {
  var paths = path.split('.')
    , current = obj
    , i;

  for (i = 0; i < paths.length; ++i) {
    if (current[paths[i]] == undefined) {
      return undefined;
    } else {
      current = current[paths[i]];
    }
  }
  return current;
}

console.log(deepFind(obj, 'foo.bar'))
@7elephant 和 qiao:如果路径的任何部分计算null. 这可能是功能或错误,这取决于您的观点。:-)
2021-03-15 08:30:35
你如何处理对象内部的数组?
2021-03-25 08:30:35

你的意思是这样的?这是一个递归版本

function recLookup(obj, path) {
    parts = path.split(".");
    if (parts.length==1){
        return obj[parts[0]];
    }
    return recLookup(obj[parts[0]], parts.slice(1).join("."));
}

http://jsfiddle.net/kExSr/

这看起来不太快。不应再次 join() 路径,只需检查路径是字符串还是数组
2021-03-31 08:30:35
金子!我能够使用它来将路径 /Root[1]/This/worked 映射到对象 {"Root[1]":This{worked:"value"}} 。不得不修剪领先的 / 并更改 . 到 / 但其他方面很漂亮。
2021-04-08 08:30:35

就像是:

function(obj, path) {
  var current=obj; 
  path.split('.').forEach(function(p){ current = current[p]; }); 
  return current;
}
另一种没有突变的方法: const lens = (obj, path) => path.split(".").reduce((o, key) => o && o[key] ? o[key] : null, obj);
2021-04-04 08:30:35

您想在点上拆分字符串,然后重复索引到对象中,例如沿着以下行:

function goDeep(obj, path) {
    var parts = path.split('.'),
        rv,
        index;
    for (rv = obj, index = 0; rv && index < parts.length; ++index) {
        rv = rv[parts[index]];
    }
    return rv;
}

活生生的例子

这是有效的,因为您可以通过几种不同的方式访问对象的属性:使用文字 ( obj.foo)的点式语法,使用字符串 ( obj["foo"])的方括号语法在后一种情况下,字符串可以是任何表达式的结果,它不必是字符串文字。在所有的中,rv设置为相同的值:

rv = obj.foo.bar;
// Or
rv = obj.foo["bar"];
// Or
f = "foo";
rv = obj[f].bar;
// Or
s = "b";
rv = obj.foo[s + "ar"];
当然,在这种情况下大多数兼容可能比完全兼容更可取:)
2021-03-14 08:30:35
当然,需求没有被表达出来,但我们可能不会怀疑 OP 可能同样想要一个函数调用,比如goDeep(myObj, 'bar[3].baz')? 这可能超出了当前问题的范围......
2021-03-19 08:30:35
(嗯,不完全,至于做到这一点,你必须基本上重新发明 [或 - 不寒而栗- 使用] eval。但是说,大部分兼容。)
2021-03-20 08:30:35
@DavidHedlund:公平的说,检查每个part的括号形式以与 JavaScript 自己的语法完全兼容可能很有用我将把它作为 OP 的练习。:-)
2021-04-08 08:30:35