I'm trying to access a property of an object using a dynamic name. Is this possible?
我正在尝试使用动态名称访问对象的属性。这是可能的吗?
const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
10 个解决方案
#1
617
There are two ways to access properties of an object:
有两种方法可以访问对象的属性:
- Dot notation:
something.bar
- 点符号:something.bar
- Bracket notation:
something['bar']
- 括号:['酒吧')
The value between the brackets can be any expression. Therefore, if the property name is stored in a variable, you have to use bracket notation:
括号之间的值可以是任何表达式。因此,如果属性名存储在变量中,则必须使用方括号表示法:
var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
#2
29
This is my solution:
这是我的解决方案:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
Usage examples:
使用例子:
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'})
#3
25
In javascript we can access with:
在javascript中,我们可以访问:
- dot notation -
foo.bar
- 点符号——foo.bar
- square brackets -
foo[someVar]
orfoo["string"]
- 方括号- foo[someVar]或foo["string"]
But only second case allows to access properties dynamically:
但只有第二种情况允许动态访问属性:
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
#4
11
Following is an ES6 example of how you can access the property of an object using a property name that has been dynamically generated by concatenating two strings.
下面是一个ES6示例,说明如何使用由连接两个字符串动态生成的属性名来访问对象的属性。
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
This is called computed property names
这被称为计算属性名
#5
9
You can achieve this in quite a few different ways.
您可以通过许多不同的方式实现这一点。
let foo = {
bar: 'Hello World'
};
foo.bar;
foo['bar'];
The bracket notation is specially powerful as it let's you access a property based on a variable:
括号表示法特别强大,因为它让你访问一个基于变量的属性:
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop];
This can be extended to looping over every property of an object. This can be seem redundant due to newer JavaScript constructs such as for ... of ..., but helps illustrate a use case:
这可以扩展为对对象的每个属性进行循环。由于更新的JavaScript结构(例如for…),这可能显得多余。的……,但有助于说明一个用例:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop in foo.getOwnPropertyNames()) {
console.log(foo[prop]);
}
Both dot and bracket notation also work as expected for nested objects:
点和括号表示法也适用于嵌套对象:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;
Object destructuring
对象解构
We could also consider object destructuring as a means to access a property in an object, but as follows:
我们还可以将对象破坏看作是访问对象中的属性的一种方法,但是如下所示:
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'
#6
1
It gets interesting when you have to pass parameters to this function as well.
当你需要将参数传递给这个函数时,它就变得有趣了。
Code jsfiddle
代码jsfiddle
var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}
var str = "method('p1', 'p2', 'p3');"
var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);
var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
// clean up param begninning
parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
// clean up param end
parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}
obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values
#7
1
UPDATE
I have take comments below into consideration and agreed. Eval is to be avoided.
我已考虑并同意以下评论。Eval是要避免的。
Accessing root properties in object is easily achieved with obj[variable]
, but getting nested complicates thing. Not to write already written code I suggest to use lodash.get
.
使用obj[变量]访问对象中的根属性很容易,但是嵌套会使事情复杂化。不要编写已经编写好的代码,我建议使用lodash.get。
Example
例子
// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);
// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);
Lodash get can be used on different ways, here is link to the documentation lodash.get
Lodash get可以以不同的方式使用,这里有Lodash .get文档链接
Old answer
Accessing nested property can be trouble doing like
object['key']
.
访问嵌套属性可能会像对象['key']那样困难。
You can use eval()
to access both nested and not nested properties or even to create reference.
您可以使用eval()来访问嵌套的和不嵌套的属性,甚至可以创建引用。
var obj = {firstLevel: 1, nested: {test: 2}};
console.log(eval('obj.firstLevel')); // 1
console.log(eval('obj.nested.test')); // 2
// creating reference
var ref = eval('obj.nested');
console.log(ref === obj.nested); // true
ref.newProperty = 3;
console.log(eval('obj.nested.newProperty')); // 3
If your object is not going to have nested properties I would suggest using []
, otherwise eval()
is better option.
如果对象没有嵌套属性,我建议使用[],否则eval()是更好的选择。
P.S.
注:
You can use eval()
also to set value.
还可以使用eval()设置值。
var newObj = {value: 1, nested: {value: 0}};
eval('newObj.value = 5');
eval('newObj.nested.value = 10');
console.log(newObj.value);
console.log(newObj.nested.value);
#8
-2
You should use JSON.parse
, take a look at https://www.w3schools.com/js/js_json_parse.asp
您应该使用JSON。解析,查看https://www.w3schools.com/js/js_json_parse.asp
const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)
#9
-3
const something = { bar: "Foobar!" };
const foo = 'bar';
something[\`${foo}\`];
#10
-6
Here is a method of getting a property or nested object from an object using path notation. It is an adaptation of a similar question answered by "Prusprus" in 2014.
这是一种使用路径符号从对象获取属性或嵌套对象的方法。这是对2014年“普鲁士舞”(Prusprus)回答的一个类似问题的改编。
I've got a configuration file with nested arrays, and want to access data from a web page by sending down a path in the form:
我有一个嵌套数组的配置文件,我想通过在表单中发送路径从web页面访问数据:
"unit_cfg[2].chn_cfg[7].chn_type"
“unit_cfg[2].chn_cfg[7].chn_type”
This function will return a single propery or an object. Yes, it can be simplified...
这个函数将返回一个属性或一个对象。是的,它可以简化……
function fetchFromObject(obj: Object, path: string): boolean | Object {
var dot_idx: number;
var lbkt_idx: number;
var rbkt_idx: number;
var prop: string;
var prop_idx: number;
var new_obj: Object;
var new_path: string;
// Return if no object.
if (typeof obj === 'undefined') {
return false;
}
// Get index of first left bracket in path.
lbkt_idx = path.indexOf('[');
// If left bracket.
if (lbkt_idx > -1) {
// Get right bracket index.
rbkt_idx = path.indexOf(']');
}
// Get index of first dot in path.
dot_idx = path.indexOf('.');
/*
* Most complicated situation is if there are both brackets
* and dots in the path. This means we have a mixture of both
* indexed and non-indexed properties:
*
* x[].y --or-- x.y[]
*
* In this case, we must see if the indexed property is before
* or after the non-indexed property.
*
* In either case, we must recurse.
*/
if ((lbkt_idx > -1) && (dot_idx > -1)) {
// If bracket is before dot: x[].y
if (lbkt_idx < dot_idx) {
// Get property string.
prop = path.substr(0, lbkt_idx);
// Get index.
prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop][prop_idx];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
// Else dot before bracket: x.y[]
else {
// Get property string.
prop = path.substr(0, dot_idx);
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
}
/*
* Else recurse if dotted property; x.y
*/
else if (dot_idx > -1) {
// Get property string.
prop = path.substr(0, dot_idx);
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
/*
* Else done if single indexed property: x[]
*/
else if (lbkt_idx > -1) {
// Get property string.
prop = path.substr(0, lbkt_idx);
// Get index.
prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
// Return with object.
return obj[prop][prop_idx];
}
/*
* Else single non-indexed property.
*/
return obj[path];
}
}
#1
617
There are two ways to access properties of an object:
有两种方法可以访问对象的属性:
- Dot notation:
something.bar
- 点符号:something.bar
- Bracket notation:
something['bar']
- 括号:['酒吧')
The value between the brackets can be any expression. Therefore, if the property name is stored in a variable, you have to use bracket notation:
括号之间的值可以是任何表达式。因此,如果属性名存储在变量中,则必须使用方括号表示法:
var foo = 'bar';
something[foo];
// both x = something[foo] and something[foo] = x work as expected
#2
29
This is my solution:
这是我的解决方案:
function resolve(path, obj) {
return path.split('.').reduce(function(prev, curr) {
return prev ? prev[curr] : null
}, obj || self)
}
Usage examples:
使用例子:
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'})
#3
25
In javascript we can access with:
在javascript中,我们可以访问:
- dot notation -
foo.bar
- 点符号——foo.bar
- square brackets -
foo[someVar]
orfoo["string"]
- 方括号- foo[someVar]或foo["string"]
But only second case allows to access properties dynamically:
但只有第二种情况允许动态访问属性:
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
#4
11
Following is an ES6 example of how you can access the property of an object using a property name that has been dynamically generated by concatenating two strings.
下面是一个ES6示例,说明如何使用由连接两个字符串动态生成的属性名来访问对象的属性。
var suffix = " name";
var person = {
["first" + suffix]: "Nicholas",
["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"
This is called computed property names
这被称为计算属性名
#5
9
You can achieve this in quite a few different ways.
您可以通过许多不同的方式实现这一点。
let foo = {
bar: 'Hello World'
};
foo.bar;
foo['bar'];
The bracket notation is specially powerful as it let's you access a property based on a variable:
括号表示法特别强大,因为它让你访问一个基于变量的属性:
let foo = {
bar: 'Hello World'
};
let prop = 'bar';
foo[prop];
This can be extended to looping over every property of an object. This can be seem redundant due to newer JavaScript constructs such as for ... of ..., but helps illustrate a use case:
这可以扩展为对对象的每个属性进行循环。由于更新的JavaScript结构(例如for…),这可能显得多余。的……,但有助于说明一个用例:
let foo = {
bar: 'Hello World',
baz: 'How are you doing?',
last: 'Quite alright'
};
for (let prop in foo.getOwnPropertyNames()) {
console.log(foo[prop]);
}
Both dot and bracket notation also work as expected for nested objects:
点和括号表示法也适用于嵌套对象:
let foo = {
bar: {
baz: 'Hello World'
}
};
foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;
Object destructuring
对象解构
We could also consider object destructuring as a means to access a property in an object, but as follows:
我们还可以将对象破坏看作是访问对象中的属性的一种方法,但是如下所示:
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'
#6
1
It gets interesting when you have to pass parameters to this function as well.
当你需要将参数传递给这个函数时,它就变得有趣了。
Code jsfiddle
代码jsfiddle
var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}
var str = "method('p1', 'p2', 'p3');"
var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);
var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
// clean up param begninning
parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
// clean up param end
parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}
obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values
#7
1
UPDATE
I have take comments below into consideration and agreed. Eval is to be avoided.
我已考虑并同意以下评论。Eval是要避免的。
Accessing root properties in object is easily achieved with obj[variable]
, but getting nested complicates thing. Not to write already written code I suggest to use lodash.get
.
使用obj[变量]访问对象中的根属性很容易,但是嵌套会使事情复杂化。不要编写已经编写好的代码,我建议使用lodash.get。
Example
例子
// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);
// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);
Lodash get can be used on different ways, here is link to the documentation lodash.get
Lodash get可以以不同的方式使用,这里有Lodash .get文档链接
Old answer
Accessing nested property can be trouble doing like
object['key']
.
访问嵌套属性可能会像对象['key']那样困难。
You can use eval()
to access both nested and not nested properties or even to create reference.
您可以使用eval()来访问嵌套的和不嵌套的属性,甚至可以创建引用。
var obj = {firstLevel: 1, nested: {test: 2}};
console.log(eval('obj.firstLevel')); // 1
console.log(eval('obj.nested.test')); // 2
// creating reference
var ref = eval('obj.nested');
console.log(ref === obj.nested); // true
ref.newProperty = 3;
console.log(eval('obj.nested.newProperty')); // 3
If your object is not going to have nested properties I would suggest using []
, otherwise eval()
is better option.
如果对象没有嵌套属性,我建议使用[],否则eval()是更好的选择。
P.S.
注:
You can use eval()
also to set value.
还可以使用eval()设置值。
var newObj = {value: 1, nested: {value: 0}};
eval('newObj.value = 5');
eval('newObj.nested.value = 10');
console.log(newObj.value);
console.log(newObj.nested.value);
#8
-2
You should use JSON.parse
, take a look at https://www.w3schools.com/js/js_json_parse.asp
您应该使用JSON。解析,查看https://www.w3schools.com/js/js_json_parse.asp
const obj = JSON.parse('{ "name":"John", "age":30, "city":"New York"}')
console.log(obj.name)
console.log(obj.age)
#9
-3
const something = { bar: "Foobar!" };
const foo = 'bar';
something[\`${foo}\`];
#10
-6
Here is a method of getting a property or nested object from an object using path notation. It is an adaptation of a similar question answered by "Prusprus" in 2014.
这是一种使用路径符号从对象获取属性或嵌套对象的方法。这是对2014年“普鲁士舞”(Prusprus)回答的一个类似问题的改编。
I've got a configuration file with nested arrays, and want to access data from a web page by sending down a path in the form:
我有一个嵌套数组的配置文件,我想通过在表单中发送路径从web页面访问数据:
"unit_cfg[2].chn_cfg[7].chn_type"
“unit_cfg[2].chn_cfg[7].chn_type”
This function will return a single propery or an object. Yes, it can be simplified...
这个函数将返回一个属性或一个对象。是的,它可以简化……
function fetchFromObject(obj: Object, path: string): boolean | Object {
var dot_idx: number;
var lbkt_idx: number;
var rbkt_idx: number;
var prop: string;
var prop_idx: number;
var new_obj: Object;
var new_path: string;
// Return if no object.
if (typeof obj === 'undefined') {
return false;
}
// Get index of first left bracket in path.
lbkt_idx = path.indexOf('[');
// If left bracket.
if (lbkt_idx > -1) {
// Get right bracket index.
rbkt_idx = path.indexOf(']');
}
// Get index of first dot in path.
dot_idx = path.indexOf('.');
/*
* Most complicated situation is if there are both brackets
* and dots in the path. This means we have a mixture of both
* indexed and non-indexed properties:
*
* x[].y --or-- x.y[]
*
* In this case, we must see if the indexed property is before
* or after the non-indexed property.
*
* In either case, we must recurse.
*/
if ((lbkt_idx > -1) && (dot_idx > -1)) {
// If bracket is before dot: x[].y
if (lbkt_idx < dot_idx) {
// Get property string.
prop = path.substr(0, lbkt_idx);
// Get index.
prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop][prop_idx];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
// Else dot before bracket: x.y[]
else {
// Get property string.
prop = path.substr(0, dot_idx);
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
}
/*
* Else recurse if dotted property; x.y
*/
else if (dot_idx > -1) {
// Get property string.
prop = path.substr(0, dot_idx);
// Get path to right of dot.
new_path = path.substr(dot_idx + 1);
// Get new object.
new_obj = obj[prop];
// Recurse.
return fetchFromObject(new_obj, new_path);
}
/*
* Else done if single indexed property: x[]
*/
else if (lbkt_idx > -1) {
// Get property string.
prop = path.substr(0, lbkt_idx);
// Get index.
prop_idx = Number(path.substring(lbkt_idx + 1, rbkt_idx));
// Return with object.
return obj[prop][prop_idx];
}
/*
* Else single non-indexed property.
*/
return obj[path];
}
}