Categories
javascript object properties

Dynamically access object property using variable

904

I’m trying to access a property of an object using a dynamic name. Is this possible?

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

1

1220

There are two ways to access properties of an object:

  • Dot notation: something.bar
  • Bracket notation: something['bar']

The value between the brackets can be any expression. Therefore, if the property name is stored in a variable, you have to use bracket notation:

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)

12

  • 45

    careful with this: javascript compilers will error here since they dont rename strings but they do rename object properties

    – chacham15

    Dec 6, 2011 at 8:40

  • 9

    Some more info on why this is possible: JS objects are associative arrays, that’s why. Further Reading: quirksmode.org/js/associative.html stackoverflow.com/questions/14031368/…

    Jun 3, 2014 at 9:00

  • 1

    @dotnetguy No they are not. Arrays are objects that inherit from the plain JS object prototype and therefore you can add properties a go-go like any plain object. The ‘associative’ behaviour is more object-like than array like. You can’t iterate the ‘associative’ version by simple index so it is not displaying array-like behaviour. You can define your ‘associative’ array as {} or [] and treat it the same in either case as far as random property access is concerned.

    Jan 3, 2017 at 16:01

  • 3

    @VanquishedWombat Not sure what your objection pertains to? I did not say that JS Objects are arrays?

    Jan 6, 2017 at 0:30

  • 1

    Please restrain from using foo-bar in the future… This explanation is so obfuscated.

    – Cornelius

    Jan 25 at 3:33

171

This is my solution:

function resolve(path, obj) {
    return path.split('.').reduce(function(prev, curr) {
        return prev ? prev[curr] : null
    }, obj || self)
}

Usage examples:

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

5

  • 4

    Excellent answer, see also: stackoverflow.com/questions/37510640/…

    Jan 3, 2019 at 13:45

  • 7

    You inspired me to create an enhanced version that allows bracket notation & property names with spaces as well as validating the inputs: it.knightnet.org.uk/kb/node-js/get-properties

    Jan 3, 2019 at 14:04

  • 3

    I love this solution. However I’m trying to modify the values in the original object, it seems your function returns a sub copy of the object. Is it possible to change it so that modifying the returned object modifies the original ?

    – Eagle1

    Feb 28, 2020 at 17:39

  • 3

    I’d also like to see the “set value” version of this.

    – GaryO

    Aug 21, 2020 at 21:05

  • 1

    Great answer! It works for deep nested properties.

    – NeNaD

    Jan 21 at 14:56

60

In javascript we can access with:

  • dot notation – foo.bar
  • square brackets – foo[someVar] or foo["string"]

But only second case allows to access properties dynamically:

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

1

  • 10

    I’m staring at 2,000 lines of if statements because the previous dev didn’t use square brackets, and statically accessed object properties by dot notation. It’s for an approval process app that has 7 different approvers and the steps are all the same. /rip

    – Chad

    Jun 7, 2018 at 14:28