使用variablesdynamic访问对象属性

我试图使用dynamic名称访问对象的属性。 这可能吗?

const something = { bar: "Foobar!" }; const foo = 'bar'; something.foo; // The idea is to access something.bar, getting "Foobar!" 

有两种方法可以访问对象的属性 :

  • 点符号: something.bar
  • 括号表示法: something['bar']

括号之间的值可以是任何expression式。 因此,如果属性名称存储在variables中,则必须使用括号表示法:

 var foo = 'bar' something[foo] 

在JavaScript中,我们可以访问:

  • 点符号 – foo.bar
  • 方括号 – foo[someVar]foo["string"]

但是只有第二种情况允许dynamic访问属性:

 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示例,说明如何使用通过连接两个stringdynamic生成的属性名称来访问对象的属性。

 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']; 

括号符号是特别强大的,因为它让你访问一个基于variables的属性:

 let foo = { bar: 'Hello World' }; let prop = 'bar'; foo[prop]; 

这可以扩展到循环对象的每个属性。 这可以看起来是多余的,由于新的JavaScript结构,如… …,但有助于说明一个用例:

 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' 

这是我的解决scheme:

 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'}) 

当你必须传递参数给这个函数时,它会变得有趣。

代码 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 

UPDATE

我已经考虑了下面的意见,并同意。 评估是要避免的。

访问对象的根属性很容易用obj[variable] ,但是嵌套复杂化。 不要写已经写好的代码,我build议使用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


老答案

访问嵌套属性可能会像object['key']一样麻烦。

您可以使用eval()来访问嵌套和非嵌套属性,甚至可以创build引用。

 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 

如果你的对象不会有嵌套的属性,我会build议使用[] ,否则eval()是更好的select。

PS

你可以使用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); 

你应该使用JSON.parse ,看看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) 
 const something = { bar: "Foobar!" }; const foo = 'bar'; something[\`${foo}\`]; 

这是一种使用path表示法从对象中获取属性或嵌套对象的方法。 这是“Prusprus”在2014年回答的类似问题的改编。

我有一个嵌套数组的configuration文件,并希望通过发送一个path的forms来访问网页中的数据:

“unit_cfg [2] .chn_cfg [7] .chn_type”

这个函数将会返回一个单个或一个对象。 是的,它可以简化…

 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-- xy[] * * 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: xy[] 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; xy */ 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]; 

}