Ben Flynn
Ben Flynn

Reputation: 18932

Using variables with nested Javascript object

Suppose I have this:

var a = { A : { AA : 1 }, B : 2 };

Is there a way for me to create a variable that could allow me to reference either AA or B? What would the syntax look like?

// I know I can do this:    
a['B']; // 2
a['A']['AA']; // 1

// something like this?
var myRef = ???;
a[myRef]; 1 or 2 depending on myRef

If not, what's a better way to get what I'm going for here?

Upvotes: 21

Views: 19885

Answers (5)

Agustí Sánchez
Agustí Sánchez

Reputation: 11253

With lodash _.get function, you can access nested properties with dot syntax.

Node server-side example:

const _ = require('lodash'); 

let item = { a: {b:'AA'}};

 _.get(item, 'a.b');

Upvotes: 2

Maximiliano Cespedes
Maximiliano Cespedes

Reputation: 391

Since i also encounter this problem, i wrote also a one line util for this (ES6):

const leaf = (obj, path) => (path.split('.').reduce((value,el) => value[el], obj))

Example:

const objSample = { owner: { name: 'Neo' } };
const pathSample = 'owner.name';

leaf(objSample, pathSample) //'Neo'

Upvotes: 16

Krizz
Krizz

Reputation: 11552

Not directly.

Solution 1 - use object flattening

Flatten object, to have new object var a = { 'A.AA' : 1; B : 2 };.

See compressing object hierarchies in JavaScript or Flattening a complex json object for mvc binding to get the javascript function for it.

Soution 2 - write key-path accessor

I can see it was already addressed by Eugen. Reposted code-reviewed version:

function Leaf(obj,path) {
  path=path.split('.');
  var res=obj;
  for (var i=0;i<path.length;i++) res=res[path[i]];
  return res;
}

Solution 3 - use eval

var x = eval("a." + myRef); // x will be 1 for myRef == "A.AA", 2 for "B"

Be careful with this solution as you may introduce some security issues. It is more of the curiosity.

Upvotes: 35

Eugen Rieck
Eugen Rieck

Reputation: 65342

function Leaf(obj,path) {
  path=path.split('.');
  var res=obj;
  for (var i=0;i<path.length;i++) obj=obj[path[i]];
  return res;
}

Leaf(a,'B')=2

Leaf(a,'A.AA')=1

Decorate with error handling etc. according to your needs.

Upvotes: 3

Andy Petrella
Andy Petrella

Reputation: 4345

Actually no, because js object are seen as property bags and doing a[X] is for accessing first level properties only...

But you could wrap the logic a['A']['AA']; // 1 in a function that does the same, like this

//WARN... no undefined check here => todo !
function _(o, path) {
  var tmp = o
  for (var i=0 ; i < path.length ; i++) {
    tmp = tmp[path[i]]
  }
  return tmp
}

var r = _(a, ['A', 'AA'])

This is pretty much the same as other answers, but the difference is when dummy boy create object property name containing dots... Like var a = {"a.a" : 3 } is valid.

Now, such problem would occurs maybe more often now with the help of IndexedDB to store anything locally...

Upvotes: 1

Related Questions