如何解决Angular/JS/Typescript-递归访问对象中的属性
假设我有一个这样定义的对象:
const me = {
id: 1,name: 'James',age: 40,family: {
mother: {
id: 101,name: 'Bea',age: 66
},father: {
id: 102,name: 'Martin',age: 69
},children: [
{
id: 11,name: 'Tom',age: 18,},{
id: 12,name: 'Nancy',age: 13,],}
如何仅通过提供链接属性名称的字符串数组轻松访问值? 例如,调用:
search(me,['family','father','age'])
相当于:
me['family']['father']['age']
将返回 69
。
PS:
让 search(me,'children','name'])
返回 ['Tom','Nancy']
怎么样?
PSS:
甚至search(me,['name','age']])
返回
[
{
name: 'Tom',age: 18
},{
name: 'Nancy',age: 13
}
]
编辑: 我去查看了 lodash/deepdash 库,但我自己无法真正弄清楚。
解决方法
您可以使用这个以数组作为查询的简单递归函数来做到这一点:
const me = {
id: 1,name: 'James',age: 40,family: {
mother: {
id: 101,name: 'Bea',age: 66
},father: {
id: 102,name: 'Martin',age: 69
},children: [
{
id: 11,name: 'Tom',age: 18,},{
id: 12,name: 'Nancy',age: 13,],}
function search(obj,[first,...rest]) {
return rest.length ? search(obj[first],rest) : obj[first];
}
const result = search(me,['family','father','age']);
console.log(result);
虽然有点长,但您可以尝试所有组合。
const me={id:1,name:'James',age:40,family:{mother:{id:101,name:'Bea',age:66},father:{id:102,name:'Martin',age:69},children:[{id:11,name:'Tom',age:18,{id:12,name:'Nancy',age:13,}
function search(data,searchPattern) {
const keys = [...searchPattern];
//picking last key and it's corresponding value
const lastKey = keys.pop();
const resultInst = keys.reduce((acc,key)=>{
return acc[key];
},data);
// if it's array iterating it further to construct the response
if (Array.isArray(resultInst)) {
return resultInst.map(inst => {
if (Array.isArray(lastKey)) {
return lastKey.reduce((accInner,key) => {
accInner[key] = inst[key];
return accInner;
},{});
} else {
return inst[lastKey];
}
});
} else {
// else just returning property's value
return resultInst[lastKey];
}
}
console.log(search(me,'age']))
console.log(search(me,'children','name']))
console.log(search(me,['name','age']]))
您有一些有趣的要求!这是使用 object-scan 和 lodash
的多合一答案// const objectScan = require('object-scan');
// const lodash = require('lodash');
const myData = { id: 1,family: { mother: { id: 101,age: 66 },father: { id: 102,age: 69 },children: [{ id: 11,age: 18 },{ id: 12,age: 13 }] } };
const search = (data,needle) => objectScan([needle],{
reverse: false,rtn: ['key','value'],useArraySelector: false,afterFn: (state) => {
if (state.result.length === 0) {
state.result = undefined;
} else if (needle.includes('{')) {
const prefixLength = lodash
.zip(...state.result.map(([k]) => k))
.findIndex((e) => new Set(e).size > 1);
const result = [];
state.result.forEach(([k,v]) => lodash.set(result,k.slice(prefixLength),v));
state.result = result;
} else if (
state.result.length === 1
&& state.result.every(([k]) => k.every((p) => typeof p === 'string'))
) {
state.result = state.result[0][1];
} else {
state.result = state.result.map(([k,v]) => v);
}
}
})(data);
console.log(search(myData,'family.father.age'));
// => 69
console.log(search(myData,'family.children.name'));
// => [ 'Tom','Nancy' ]
console.log(search(myData,'family.children.{age,name}'));
// => [ { name: 'Tom',{ name: 'Nancy',age: 13 } ]
console.log(search(myData,'family.father.unknown'));
// => undefined
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@16.0.2"></script>
<script src="https://bundle.run/lodash@4.17.21"></script>
免责声明:我是object-scan
的作者版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。