[javascript] Dynamically access object property using variable

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!"

This question is related to javascript object properties

The answer is


Whenever you need to access property dynamically you have to use square bracket for accessing property not "." operator
Syntax: object[propery}

_x000D_
_x000D_
const something = { bar: "Foobar!" };_x000D_
const foo = 'bar';_x000D_
// something.foo; -- not correct way at it is expecting foo as proprty in  something={ foo: "value"};_x000D_
// correct way is  something[foo]_x000D_
alert( something[foo])
_x000D_
_x000D_
_x000D_


You can do it like this using Lodash get

_.get(object, 'a[0].b.c');

You should use JSON.parse, take a look at 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)

Access dynamic object properties in js we can use bracket notation.

const something = { 
  bar: "Foobar!" 
};
const foo = 'bar';

console.log(something[foo]); // "Foobar!"

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

You can achieve this in quite a few different ways.

let foo = {
    bar: 'Hello World'
};

foo.bar;
foo['bar'];

The bracket notation is specially powerful as it let's you access a property based on a variable:

let foo = {
    bar: 'Hello World'
};

let prop = 'bar';

foo[prop];

This can be extended to looping over every property of an object. This can be seem redundant due to newer JavaScript constructs such as for ... of ..., but helps illustrate a use case:

let foo = {
    bar: 'Hello World',
    baz: 'How are you doing?',
    last: 'Quite alright'
};

for (let prop in foo.getOwnPropertyNames()) {
    console.log(foo[prop]);
}

Both dot and bracket notation also work as expected for nested objects:

let foo = {
    bar: {
        baz: 'Hello World'
    }
};

foo.bar.baz;
foo['bar']['baz'];
foo.bar['baz'];
foo['bar'].baz;

Object destructuring

We could also consider object destructuring as a means to access a property in an object, but as follows:

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'

Following is an ES6 example of how you can access the property of an object using a property name that has been dynamically generated by concatenating two strings.

var suffix = " name";

var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};

console.log(person["first name"]);      // "Nicholas"
console.log(person["last name"]);       // "Zakas"

This is called computed property names


const something = { bar: "Foobar!" };
const foo = 'bar';

something[\`${foo}\`];

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

For anyone looking to set the value of a nested variable, here is how to do it:

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

Documentation: https://lodash.com/docs/4.17.15#set

Also, documentation if you want to get a value: https://lodash.com/docs/4.17.15#get


It gets interesting when you have to pass parameters to this function as well.

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

Finding Object by reference without, strings, Note make sure the object you pass in is cloned , i use cloneDeep from lodash for that

if object looks like

const obj = {data: ['an Object',{person: {name: {first:'nick', last:'gray'} }]

path looks like

const objectPath = ['data',1,'person',name','last']

then call below method and it will return the sub object by path given

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
}

ES5 // Check Deeply Nested Variables

This simple piece of code can check for deeply nested variable / value existence without having to check each variable along the way...

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

Ex. - a deeply nested array of objects:

a = [ 
    {
      b : [
          {
             a : 1,
             b : [
                 {
                    c : 1,
                    d : 2   // we want to check for this
                 }
             ]
           }
      ]
    } 
]

Instead of :

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

We can now :

if( getValue('a[0].b[0].b[0].d') == 2 ) // true

Cheers!


UPDATED

I have take comments below into consideration and agreed. Eval is to be avoided.

Accessing root properties in object is easily achieved with obj[variable], but getting nested complicates thing. Not to write already written code I suggest to use lodash.get.

Example

// Accessing root property
var rootProp = 'rootPropert';
_.get(object, rootProp, defaultValue);

// Accessing nested property
var listOfNestedProperties = [var1, var2];
_.get(object, listOfNestedProperties);

Lodash get can be used on different ways, here is link to the documentation lodash.get


I asked a question that kinda duplicated on this topic a while back, and after excessive research, and seeing a lot of information missing that should be here, I feel I have something valuable to add to this older post.

  • Firstly I want to address that there are several ways to obtain the value of a property and store it in a dynamic Variable. The first most popular, and easiest way IMHO would be:
let properyValue = element.style['enter-a-property'];

however I rarely go this route because it doesn't work on property values assigned via style-sheets. To give you an example, I'll demonstrate with a bit of pseudo code.

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

Using the code example above; if the width property of the div element that was stored in the 'elem' variable was styled in a CSS style-sheet, and not styled inside of its HTML tag, you are without a doubt going to get a return value of undefined stored inside of the cssProp variable. The undefined value occurs because in-order to get the correct value, the code written inside a CSS Style-Sheet needs to be computed in-order to get the value, therefore; you must use a method that will compute the value of the property who's value lies within the style-sheet.

  • Henceforth the getComputedStyle() method!
function getCssProp(){
  let ele = document.getElementById("test");
  let cssProp = window.getComputedStyle(ele,null).getPropertyValue("width");
}

W3Schools getComputedValue Doc This gives a good example, and lets you play with it, however, this link Mozilla CSS getComputedValue doc talks about the getComputedValue function in detail, and should be read by any aspiring developer who isn't totally clear on this subject.

  • As a side note, the getComputedValue method only gets, it does not set. This, obviously is a major downside, however there is a method that gets from CSS style-sheets, as well as sets values, though it is not standard Javascript. The JQuery method...
$(selector).css(property,value)

...does get, and does set. It is what I use, the only downside is you got to know JQuery, but this is honestly one of the very many good reasons that every Javascript Developer should learn JQuery, it just makes life easy, and offers methods, like this one, which is not available with standard Javascript. Hope this helps someone!!!


I came across a case where I thought I wanted to pass the "address" of an object property as data to another function and populate the object (with AJAX), do lookup from address array, and display in that other function. I couldn't use dot notation without doing string acrobatics so I thought an array might be nice to pass instead. I ended-up doing something different anyway, but seemed related to this post.

Here's a sample of a language file object like the one I wanted data from:

const locs = {
  "audioPlayer": {
    "controls": {
      "start": "start",
      "stop": "stop"
    },
    "heading": "Use controls to start and stop audio."
  }
}

I wanted to be able to pass an array such as: ["audioPlayer", "controls", "stop"] to access the language text, "stop" in this case.

I created this little function that looks-up the "least specific" (first) address parameter, and reassigns the returned object to itself. Then it is ready to look-up the next-most-specific address parameter if one exists.

function getText(selectionArray, obj) {
  selectionArray.forEach(key => {
    obj = obj[key];
  });
  return obj;
}

usage:

/* returns 'stop' */
console.log(getText(["audioPlayer", "controls", "stop"], locs)); 

/* returns 'use controls to start and stop audio.' */
console.log(getText(["audioPlayer", "heading"], locs)); 

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to object

How to update an "array of objects" with Firestore? how to remove json object key and value.? Cast object to interface in TypeScript Angular 4 default radio button checked by default How to use Object.values with typescript? How to map an array of objects in React How to group an array of objects by key push object into array Add property to an array of objects access key and value of object using *ngFor

Examples related to properties

Property 'value' does not exist on type 'EventTarget' How to read data from java properties file using Spring Boot Kotlin - Property initialization using "by lazy" vs. "lateinit" react-router - pass props to handler component Specifying trust store information in spring boot application.properties Can I update a component's props in React.js? Property getters and setters Error in Swift class: Property not initialized at super.init call java.util.MissingResourceException: Can't find bundle for base name 'property_file name', locale en_US How to use BeanUtils.copyProperties?