【问题标题】:How to get object property dynamically using a custom function如何使用自定义函数动态获取对象属性
【发布时间】:2021-12-09 00:56:36
【问题描述】:

我有一个接受属性名称的函数

func(propertyName) {
  return object[propertyName];
}

所以通过调用func('value') 将返回object.value

但是对象很复杂,所以它有内在的道具

我想做的是能够做到这一点func('property1.property2')

最好的方法是什么?

【问题讨论】:

标签: javascript json object properties propertypath


【解决方案1】:

reduceOptional chaining operator 的组合可确保在任何传递的类型/对象处对任何传递的属性键路径进行故障安全实现和故障安全访问...

function getValueByKeyPath(obj, path) {
  return String(path)
    .split('.')
    .reduce((value, key) => value?.[key], Object(obj))
}

const sampleData = {
  foo: {
    value: 'foo',
    bar: {
      value: 'bar',
      baz: {
        value: 'baz',
      },
    },
  },
};

console.log(
  "getValueByKeyPath(sampleData, 'foo.bar.baz') ...",
  getValueByKeyPath(sampleData, 'foo.bar.baz')
);
console.log(
  "getValueByKeyPath(sampleData, 'foo.bar.baz.value') ...",
  getValueByKeyPath(sampleData, 'foo.bar.baz.value')
);

console.log(
  "\nfail safe ... getValueByKeyPath(sampleData, 'foo.biz.baz.value') ...",
  getValueByKeyPath(sampleData, 'foo.biz.baz.value')
);

console.log(
  "\nfail safe ... getValueByKeyPath('', 'toString') ...",
  getValueByKeyPath('', 'toString')
);
console.log(
  "fail safe ... getValueByKeyPath(null, '') ...",
  getValueByKeyPath(null, '')
);
console.log(
  "fail safe ... getValueByKeyPath() ...",
  getValueByKeyPath()
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

上述方法可以扩展到括号​​表示法,包括带引号和不带引号的键,例如基于嵌套/混合对象和数组的数据结构。然后,在捕获括号内的值时,不会在任何点处拆分键路径,而是在任何开始和结束括号处拆分键路径。这种拆分操作的结果需要从一些虚假工件中清除,减少部分保持不变......

function getValueByKeyPath(obj, path) {
  return String(path)
    .split(/\.|\[['"]?([^'"\]]*)['"]?\]/)
    .filter(elm => !!elm)
    .reduce((value, key) => value?.[key], Object(obj))
}

const sampleDataA = {
  foo: {
    value: 'foo',
    bar: {
      value: 'bar',
      baz: {
        value: 'baz',
      },
    },
  },
};
const sampleDataB = {
  foo: {
    bar: [{
      baz: {
        value: 'baz',
        biz: {
          value: 'biz',
        },
      }
    }, {
      buzz: {
        value: 'buzz',
        booz: {
          value: 'booz',
        },
      }
    }],
  },
};

console.log(
  "getValueByKeyPath(sampleDataA, 'foo.bar.baz.value') ...",
  getValueByKeyPath(sampleDataA, 'foo.bar.baz.value')
);
console.log(
  "getValueByKeyPath(sampleDataA, 'foo.bar[\"baz\"].value') ...",
  getValueByKeyPath(sampleDataA, 'foo.bar["baz"].value')
);
console.log(
  "getValueByKeyPath(sampleDataB, 'foo.bar[1][\"buzz\"].booz') ...",
  getValueByKeyPath(sampleDataB, 'foo.bar[1]["buzz"].booz')
);
console.log(
  "fail safe ... getValueByKeyPath(sampleDataB, 'foo.bar[2].buzz.booz') ...",
  getValueByKeyPath(sampleDataB, 'foo.bar[2].buzz.booz')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

【讨论】:

  • btw the highest rated and accepted answer 上面发布的重复链接如果像Object.byString(sampleDataB, 'foo.bar[1]["buzz"].booz'); 一样调用它会失败,而它确实适用于Object.byString(sampleDataB, 'foo.bar[1].buzz.booz')。因此,Object.byString 提供的实现在正确处理带引号的字符串的括号表示法方面是不可靠的。
  • 我喜欢这个来自同一个线程stackoverflow.com/a/41326547/2926340
  • @sreginogemoh ...好吧,这两种方法背后的基本思想是相同的。这两种方法也都专注于处理不可靠的参数以及如何使用现成的消费对象退出迭代。然而,我想说.split().filter().reduce() 的 3 个命令(链式操作)比带有for 循环和处理continue 和多个returns 的链接方法更具表现力/可读性。
【解决方案2】:

试试这个:

示例数据: a={b:{c:"hellooo"}};

功能: function getValue(object,propertyName){ return propertyName.split(".").reduce((a,c)=>a[c],object); }

回复:

getValue(a,"b.c") = hellooo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-06-08
    • 2011-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多