我正在尝试使用动态名称访问对象的属性。 这是可能的吗?
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!"
访问对象的属性有两种方式:点符号表示法和括号表示法:
something.bar
something['bar']
方括号中的值可以是任何表达式。因此,如果属性名称存储在变量中,则必须使用括号表示法:
var something = {
bar: 'foo'
};
var foo = 'bar';
// both x = something[foo] and something[foo] = x work as expected
console.log(something[foo]);
console.log(something.bar)
这是我的解决方案:
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'})
在 JavaScript 中,我们可以使用以下方式进行访问:
foo.bar
foo[someVar]
或 foo["string"]
但只有第二种情况允许动态访问属性:
var foo = { pName1 : 1, pName2 : [1, {foo : bar }, 3] , ...}
var name = "pName"
var num = 1;
foo[name + num]; // 1
// --
var a = 2;
var b = 1;
var c = "foo";
foo[name + a][b][c]; // bar
以下是一个ES6示例,演示了如何使用通过连接两个字符串动态生成的属性名称来访问对象的属性。
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
这被称为计算属性名
你可以用很多不同的方式来实现这个目标。
let foo = {
bar: 'Hello World'
};
foo.bar;
foo['bar'];
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop];
可以将此扩展到遍历对象的每个属性。这似乎是多余的,因为有了新的JavaScript构造,比如for ... of ...,但它有助于说明用例:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop in foo.getOwnPropertyNames()) {
console.log(foo[prop]);
}
点符号和方括号符号在处理嵌套对象时也能按预期工作:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;
对象解构
我们也可以考虑使用对象解构来访问对象中的属性,方法如下:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
let prop = 'last';
let { bar, baz, [prop]: customName } = foo;
// bar = 'Hello World'
// baz = 'How are you doing?'
// customName = 'Quite alright'
_.get(object, 'a[0].b.c');
通过obj[variable]
可以轻松访问对象中的根属性,但是获取嵌套属性会更加复杂。为了避免重复编写已有的代码,建议使用lodash.get
。
示例
// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);
// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);
Lodash get 可以以不同的方式使用,有关文档请参阅 lodash.get
eval
是最好的选择。https://dev59.com/c3VD5IYBdhLWcg3wGXpI - Lukeeval
是过度杀鸡,不建议在任何情况下都这样做。如果你想访问嵌套对象中的属性,请使用obj['nested']['test']
,这非常有效,并且不需要在字符串中嵌入代码。"麻烦"是什么? - Kyll_.get
引入讨论的人。我认为这个答案现在应该得到赞而不是踩。虽然可能有些过度,但知道它的存在还是很好的。 - Emile Bergeron要动态访问属性,只需使用方括号 [][]
即可:
const something = { bar: "Foobar!" };
const userInput = 'bar';
console.log(something[userInput])
这种解决方案存在一个重大的问题!(我很惊讶其他答案尚未提及此问题)。通常,您只想访问自己放置在对象上的属性,而不想获取继承的属性。
以下是此问题的示例。这里有一个看起来无害的程序,但它有一个微妙的错误-你能发现它吗?
const agesOfUsers = { sam: 16, sally: 22 }
const username = prompt('Enter a username:')
if (agesOfUsers[username] !== undefined) {
console.log(`${username} is ${agesOfUsers[username]} years old`)
} else {
console.log(`${username} is not found`)
}
agesOfUsers
是一个对象,因此自动继承基本Object类的某些属性,如.toString()
。您可以在这里查看所有对象继承的完整属性列表。
const agesOfUsers = new Map()
agesOfUsers.set('sam', 16)
agesOfUsers.set('sally', 2)
console.log(agesOfUsers.get('sam')) // 16
Object.create(null)
来创建这样的对象。这种类型的对象不会受到这些原型问题的困扰,因为你明确地创建了它,使其不继承任何东西。const agesOfUsers = Object.create(null)
agesOfUsers.sam = 16
agesOfUsers.sally = 22;
console.log(agesOfUsers['sam']) // 16
console.log(agesOfUsers['toString']) // undefined - toString was not inherited
Object.hasOwn(yourObj, attrName)
先检查你想要访问的动态键是否直接在对象上而不是继承而来(了解更多请点击 这里)。这是一个相对较新的特性,因此在将其放入代码之前,请先检查兼容性表。在 Object.hasOwn(yourObj, attrName)
出现之前,您可以通过 Object.prototype.hasOwnProperty.call(yourObj, attrName)
实现同样的效果。有时候,你可能会看到代码使用 yourObj.hasOwnProperty(attrName)
,它有时候也能工作,但是它有一些缺陷,你可以在 这里 读到相关信息。// Try entering the property name "toString",
// you'll see it gets handled correctly.
const user = { name: 'sam', age: 16 }
const propName = prompt('Enter a property name:')
if (Object.hasOwn(user, propName)) {
console.log(`${propName} = ${user[propName]}`)
} else {
console.log(`${propName} is not found`)
}
const locs = {
"audioPlayer": {
"controls": {
"start": "start",
"stop": "stop"
},
"heading": "Use controls to start and stop audio."
}
}
function getText(selectionArray, obj) {
selectionArray.forEach(key => {
obj = obj[key];
});
return obj;
}
使用方法:
/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs));
/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs));
这段简单的代码可以检查深度嵌套变量/值的存在性,而无需沿途检查每个变量...
var getValue = function( s, context ){
return Function.call( context || null, 'return ' + s )();
}
例如:- 一个深度嵌套的对象数组:
a = [
{
b : [
{
a : 1,
b : [
{
c : 1,
d : 2 // we want to check for this
}
]
}
]
}
]
替代方案:
if(a && a[0] && a[0].b && a[0].b[0] && a[0].b[0].b && a[0].b[0].b[0] && a[0].b[0].b[0].d && a[0].b[0].b[0].d == 2 ) // true
if( getValue('a[0].b[0].b[0].d') == 2 ) // true
干杯!
Function
代替。 - user4602228Function.call()
仍然是一种 eval 形式(您仍然将 JavaScript 作为字符串进行评估,只是没有显式调用 eval 函数),这并没有解决任何问题。 - Scotty Jamison