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

IT技术 javascript object properties
2021-01-05 21:26:20

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

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

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

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

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

var something = {
  bar: 'foo'
};
var foo = 'bar';

// both x = something[foo] and something[foo] = x work as expected
console.log(something[foo]);
console.log(something.bar)

小心这一点:javascript 编译器会在这里出错,因为它们不会重命名字符串,但会重命名对象属性
2021-02-09 21:26:20
@dotnetguy 不,他们不是。数组是从普通 JS 对象原型继承的对象,因此您可以像任何普通对象一样添加属性。“关联”行为比数组更像对象。您不能通过简单的索引迭代“关联”版本,因此它不会显示类似数组的行为。您可以将“关联”数组定义为 {} 或 [],并就随机属性访问而言,在任何一种情况下都将其视为相同。
2021-02-12 21:26:20
@VanquishedWombat 不确定您的反对意见是什么?我不是说JS Objects是数组吗?
2021-02-14 21:26:20
关于为什么这是可能的更多信息:JS 对象是关联数组,这就是原因。进一步阅读:quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/...
2021-02-22 21:26:20
作为正确答案的参考参考
2021-02-23 21:26:20

这是我的解决方案:

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'})
我喜欢这个解决方案。但是,我正在尝试修改原始对象中的值,看来您的函数返回了该对象的子副本。是否可以更改它以便修改返回的对象会修改原始对象?
2021-02-07 21:26:20
很好的答案,另见:stackoverflow.com/questions/37510640/...
2021-02-17 21:26:20
您启发我创建了一个增强版本,允许括号符号和带有空格的属性名称以及验证输入:it.knightnet.org.uk/kb/node-js/get-properties
2021-02-23 21:26:20
我也想看看这个的“设定值”版本。
2021-03-05 21:26:20

在javascript中,我们可以访问:

  • 点符号 - 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
我盯着 2,000 行 if 语句,因为之前的开发人员没有使用方括号,而是通过点表示法静态访问对象属性。它适用于具有 7 个不同审批者且步骤都相同的审批流程应用程序。/rip
2021-02-15 21:26:20

以下是一个 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 结构(例如 for ... of ...),这似乎是多余的,但有助于说明用例:

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'