我试图使用动态名称访问对象的属性。这可能吗?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
我试图使用动态名称访问对象的属性。这可能吗?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
当前回答
通过引用查找对象,字符串, 注意,确保你传递的对象是克隆的,我使用cloneDeep从lodash
如果对象看起来像
const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]
路径看起来像这样
const objectPath = ['data',1,'person',name','last']
然后调用下面的方法,它将按给定的路径返回子对象
const child = findObjectByPath(obj, objectPath)
alert( child) // alerts "last"
const findObjectByPath = (objectIn: any, path: any[]) => {
let obj = objectIn
for (let i = 0; i <= path.length - 1; i++) {
const item = path[i]
// keep going up to the next parent
obj = obj[item] // this is by reference
}
return obj
}
其他回答
下面是一个ES6示例,说明如何使用通过连接两个字符串动态生成的属性名访问对象的属性。
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
这称为计算属性名
这是我的解决方案:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
使用例子:
resolve("document.body.style.width")
// or
resolve("style.width", document.body)
// or even use array indexes
// (someObject has been defined in the question)
resolve("part.0.size", someObject)
// returns null when intermediate properties are not defined:
resolve('properties.that.do.not.exist', {hello:'world'})
要动态访问属性,只需使用方括号[],如下所示:
const something = {bar: "Foobar!"}; const userInput = 'bar'; console.log ([userInput])
这个问题
这个解决方案有个大问题!(我很惊讶其他答案还没有提到这一点)。通常你只想访问你自己放在对象上的属性,你不想获取继承的属性。
这里有一个关于这个问题的例子。这里我们有一个看似无辜的程序,但它有一个微妙的错误-你能发现它吗?
const agesOfUsers = {sam: 16, sally: 22} const username = prompt('输入用户名:') if (agesOfUsers[username] !== undefined) { console.log(' ${username}是${agesOfUsers[username]}年') }其他{ Console.log (' ${username}未找到') }
当提示输入用户名时,如果你提供“toString”作为用户名,它会给你以下消息:“toString is function toString(){[原生代码]}years old”。问题是agesOfUsers是一个对象,因此会自动从基object类继承某些属性,如. tostring()。您可以在这里查找所有对象继承的属性的完整列表。
解决方案
请使用Map数据结构。映射的存储内容不会受到原型问题的影响,因此它们为这个问题提供了一个干净的解决方案。
const agesOfUsers = new Map() agesOfUsers。设置(“山姆”,16) agesOfUsers。设置(“莎莉”,2) console.log(agesOfUsers.get('sam')) // 16
使用具有空原型的对象,而不是默认原型。你可以使用object. create(null)来创建这样一个对象。这种类型的对象不会受到这些原型问题的影响,因为您已经显式地创建了它,它不会继承任何东西。
const agesOfUsers = Object.create(null) agesOfUsers。山姆= 16 agesOfUsers。莎莉= 22; console.log(agesOfUsers['sam']) // 16 console.log(agesOfUsers['toString']) // undefined - toString没有被继承
You can use Object.hasOwn(yourObj, attrName) to first check if the dynamic key you wish to access is directly on the object and not inherited (learn more here). This is a relatively newer feature, so check the compatibility tables before dropping it into your code. Before Object.hasOwn(yourObj, attrName) came around, you would achieve this same effect via Object.prototype.hasOwnProperty.call(yourObj, attrName). Sometimes, you might see code using yourObj.hasOwnProperty(attrName) too, which sometimes works but it has some pitfalls that you can read about here.
//尝试输入属性名"toString" //你会看到它被正确处理。 Const user = {name: 'sam',年龄:16} const propName = prompt('输入属性名:') 如果对象。hasOwn(user, propName)) { console.log(' ${propName} = ${user[propName]} ') }其他{ console.log(' ${propName}未找到') }
如果你知道你试图使用的键永远不会是一个继承属性的名称(例如,可能它们是数字,或者它们都有相同的前缀,等等),你可以选择使用原始的解决方案。
对于任何想要设置嵌套变量值的人来说,下面是如何做的:
const _ = require('lodash'); //import lodash module
var object = { 'a': [{ 'b': { 'c': 3 } }] };
_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
文档:https://lodash.com/docs/4.17.15
另外,如果您想获得一个值,可以查看文档:https://lodash.com/docs/4.17.15#get
你可以像这样使用Lodash get
_.get(object, 'a[0].b.c');