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

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

当前回答

要动态访问属性,只需使用方括号[],如下所示:

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}未找到') }

如果你知道你试图使用的键永远不会是一个继承属性的名称(例如,可能它们是数字,或者它们都有相同的前缀,等等),你可以选择使用原始的解决方案。

其他回答

ES5 //检查深嵌套变量

这段简单的代码可以检查嵌套深度的变量/值是否存在,而不需要检查每个变量…

var getValue = function( s, context ){
    return Function.call( context || null, 'return ' + s )();
}

Ex. -嵌套很深的对象数组:

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

干杯!

其他人已经提到了“点”和“方”语法,所以我想以类似的方式介绍访问函数和发送参数。

Code 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

演示对象示例

let obj = {
    name: {
        first_name: "Bugs",
        last_name: "Founder",
        role: "Programmer"
    }
}

的值的虚线字符串键

let key = "name.first_name"

函数

const getValueByDottedKeys = (obj, strKey)=>{
    let keys = strKey.split(".")
    let value = obj[keys[0]];   
    for(let i=1;i<keys.length;i++){
        value = value[keys[i]]
    }
    return value
}

调用getValueByDottedKeys函数

value = getValueByDottedKeys(obj, key)
console.log(value)

输出

Bugs

const getValueByDottedKeys = (obj, strKey)=>{ 让键= strKey.split(".") Let value = obj[keys[0]]; (让我= 1,< keys.length;我+ +){ Value = Value [key [i]] } 返回值 } 让obj = { 名称:{ first_name:“虫子”, last_name:“创始人”, 作用:“程序员” } } Let key = "name.first_name" value = getValueByDottedKeys(obj, key) console.log(值)

要动态访问属性,只需使用方括号[],如下所示:

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}未找到') }

如果你知道你试图使用的键永远不会是一个继承属性的名称(例如,可能它们是数字,或者它们都有相同的前缀,等等),你可以选择使用原始的解决方案。

我也遇到了同样的问题,但是lodash模块在处理嵌套属性时受到了限制。我按照递归后代解析器的思想编写了一个更通用的解决方案。该解决方案适用于以下要点:

递归下降对象解引用