Javascript 使用变量动态访问对象属性

Javascript 使用变量动态访问对象属性,javascript,object,properties,Javascript,Object,Properties,我正在尝试使用动态名称访问对象的属性。这可能吗 const something = { bar: "Foobar!" }; const foo = 'bar'; something.foo; // The idea is to access something.bar, getting "Foobar!" 一个对象有以下几种类型: 点符号:something.bar 括号符号:某物['bar'] 括号之间的值可以是任何表达式。因此,如果属性名称存储在变量中,则必须使用括号表示法: var某物

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

const something = { bar: "Foobar!" };
const foo = 'bar';
something.foo; // The idea is to access something.bar, getting "Foobar!"
一个对象有以下几种类型:

点符号:something.bar 括号符号:某物['bar'] 括号之间的值可以是任何表达式。因此,如果属性名称存储在变量中,则必须使用括号表示法:

var某物={ 酒吧:“富” }; var foo='bar'; //x=something[foo]和something[foo]=x都按预期工作 console.logsomething[foo];
在javascript中,我们可以通过以下方式访问console.logsomething.bar:

点符号-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
更新 使用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可以以不同的方式使用,下面的文档是一个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结构,例如。。。但有助于说明一个用例:

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'
您应该使用JSON.parse,看看

这是我的解决方案:

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

您可以使用Lodash get这样做

_.get(object, 'a[0].b.c');
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

干杯

不久前,我问了一个关于这个话题的问题,这个问题有点重复。经过过多的研究,我发现这里缺少了很多信息,我觉得我有一些有价值的东西可以补充到这篇老文章中

首先,我想说明有几种方法可以获取属性值并将其存储在动态变量中。IMHO的第一个最流行、最简单的方法是: 但是,我很少这样做,因为它不适用于通过样式表指定的属性值。为了给你一个例子,我将用一些伪代码来演示

 let elem = document.getElementById('someDiv');
 let cssProp = elem.style['width'];

使用上面的代码示例;如果存储在'elem'变量中的div元素的width属性是在CSS样式表中设置的,而不是在其HTML标记中设置的,那么毫无疑问,您将获得存储在cssProp变量中的undefined返回值。出现未定义的值是因为为了获得正确的值,需要计算写在CSS样式表中的代码以获得值;必须使用一种方法来计算样式表中的属性值

从今往后,使用getComputedStyle方法! 这提供了一个很好的示例,让您可以使用它,但是,此链接详细介绍了getComputedValue函数,任何有志于此的开发人员都应该阅读此链接,但他们对此主题并不完全清楚

作为旁注,getComputedValue方法只获取,不设置。这显然是一个主要的缺点,但是有一个方法可以从CSS样式表中获取并设置值,尽管它不是标准的Javascript。 JQuery方法。。。 …得到了,也得到了。这就是我所使用的,唯一的缺点是你了解了JQuery,但这是每个Javascript开发人员都应该学习JQuery的一个很好的理由,它只是让生活变得简单,并提供了标准Javascript所不具备的方法,比如这个方法。
希望这对别人有帮助

我遇到了一个例子,我想我想把一个对象属性的地址作为数据传递给另一个函数,并用AJAX填充对象,从地址数组进行查找,然后在另一个函数中显示。我不能在不做字符串杂技的情况下使用点表示法,所以我认为可以用数组来代替。我最终做了一些不同的事情,但似乎与这篇文章有关

下面是一个语言文件对象的示例,类似于我希望从中获取数据的对象:

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}
我希望能够通过[audioPlayer,controls,stop]这样的数组访问语言文本,st 在这种情况下

我创建了这个小函数,它查找最不特定的第一个地址参数,并将返回的对象重新分配给它自己。然后,它准备查找下一个最具体的地址参数(如果存在)

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)); 

对于希望设置嵌套变量值的任何人,以下是如何进行设置:

const _ = require('lodash'); //import lodash module

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
文件:


另外,如果要获取值,请参阅文档:

通过引用查找对象,不带字符串, 请注意,请确保您传入的对象已克隆,我使用lodash中的cloneDeep进行克隆

如果对象看起来像

const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]
const objectPath = ['data',1,'person',name','last']
路径看起来像

const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]
const objectPath = ['data',1,'person',name','last']
然后调用下面的方法,它将按照给定的路径返回子对象

const child = findObjectByPath(obj, objectPath)
alert( child) // alerts "last"


const findObjectByPath = (objectIn: any, path: any[]) => {
    let obj = objectIn
    for (let i = 0; i <= path.length - 1; i++) {
        const item = path[i]
        // keep going up to the next parent
        obj = obj[item] // this is by reference
    }
    return obj
}


注意:javascript编译器在这里会出错,因为它们不会重命名字符串,但会重命名对象属性。有关这一点的更多信息:JS对象是关联数组,这就是原因。进一步阅读:@dotnetguy不,他们不是。数组是从普通JS对象原型继承的对象,因此可以像任何普通对象一样添加属性。“关联”行为更像对象而不是数组。不能通过简单索引迭代“关联”版本,因此它不会显示类似数组的行为。您可以将“关联”数组定义为{}或[],并在任意一种情况下,就随机属性访问而言,对其进行相同的处理。@VanquishedWombat不确定您的反对意见与什么有关?我没有说JS对象是数组?作为正确答案的参考,请参阅,最好尽可能避免使用eval。将eval用于访问属性等琐碎的事情显然是过分的,在任何情况下都不可取。有什么问题吗?obj['nested']['test']工作得很好,不需要在字符串中嵌入代码。eval的速度要慢三倍或更多,我不建议新手使用它,因为它可能会教他们坏习惯。我使用obj['nested']['value']-记住,孩子们,eval是邪恶的@卢克,他现在是唯一想把洛达斯带来的人。到桌子上去。我认为这个答案现在值得投赞成票,而不是反对票。这可能有点过分了,但知道它的存在是件好事。谢谢你为此介绍洛达斯。我是通过谷歌来这里寻找一种方法来设置对象深处的值的,并使用了他们的u.set方法,该方法与上面的方法相同,但对要设置的值有额外的争论。你到底为什么要这样做?您的foo已经是一个字符串,因此`${foo}`与foo完全相同。此外,您的代码似乎有一些额外的反斜杠,不属于那里。但即使修复了语法错误,它仍然毫无意义。我现在看到2000行if语句,因为以前的开发人员没有使用方括号,而是通过点符号静态访问对象属性。它适用于一个审批流程应用程序,该应用程序有7个不同的审批人,并且步骤都是相同的/很好的回答,另请参见:您启发我创建了一个增强版,允许使用括号表示法和带空格的属性名,以及验证输入:我喜欢这个解决方案。然而,我试图修改原始对象中的值,您的函数似乎返回了对象的子副本。是否可以更改它,以便修改返回的对象修改原始对象?我还希望看到此设置值的版本。在许多情况下,例如深度嵌套对象查找,这是唯一的选项。jQuery不够。如果解决方案是使用eval,您只会创建一百万个其他问题。@RodrigoLeite ok,所以,至少给出一个……给你:@RodrigoLeite我已经阅读了它,并更新了使用函数代替函数的解决方案ECMAScript 2020中正确的方法是使用:ifa?[0]?.b?[0]?.b?[0]?.d==2{…}。
const _ = require('lodash'); //import lodash module

var object = { 'a': [{ 'b': { 'c': 3 } }] };

_.set(object, 'a[0].b.c', 4);
console.log(object.a[0].b.c);
// => 4
const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]
const objectPath = ['data',1,'person',name','last']
const child = findObjectByPath(obj, objectPath)
alert( child) // alerts "last"


const findObjectByPath = (objectIn: any, path: any[]) => {
    let obj = objectIn
    for (let i = 0; i <= path.length - 1; i++) {
        const item = path[i]
        // keep going up to the next parent
        obj = obj[item] // this is by reference
    }
    return obj
}