使用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];
}