4
let foo = {};

const key1 = 'a';
const key2 = 'b';
const key3 = 'c';

foo[key1][key2][key3] = [1, 2];

When I trying to do something similar I get:

Uncaught TypeError: Cannot read property 'b' of undefined
2
  • In that given codesnippet you are trying to access key1 in foo which is undefined. Undefined is the default value that a given key in a json object will be considered as. However you are then trying to access a KEY VALUE from foo[key1] where foo[key1] = undefined. Assign appropriate key value pairs in the json and it should work Commented Jun 17, 2019 at 19:22
  • if you are using lodash, _.get for reading object's value through a dot-notation string, _.set for setting object's dot-notation nested value. lodash doc .set .get
    – tinystone
    Commented Nov 17, 2023 at 16:02

5 Answers 5

8

You have to create the nested object before you can create a property in it.

let foo = {}

const key1 = 'a'
const key2 = 'b'
const key3 = 'c'

foo[key1] = {};
foo[key1][key2] = {};
foo[key1][key2][key3] = [1, 2];
console.log(foo);

If the list of keys is generated dynamically in an array, see Populate nested object from array? for a function to create all the objects.

1
  • I would have demonstrated with: console.log(foo.a.b.c);
    – Wyck
    Commented Jun 17, 2019 at 19:24
5

You can also create the literal object with dynamic keys. Just make sure to create nested objects where necessary as @Barmar demonstrated.

const key1 = 'a'
const key2 = 'b'
const key3 = 'c'

let foo = { [key1]: { [key2]: { [key3]: [1, 2] } } };

console.log(foo.a.b.c);

2

Using Array#reduce will make this possible, however the keys need to be in a list and in reverse order.

const key1 = 'a'
const key2 = 'b'
const key3 = 'c'

const foo = [key3, key2, key1].reduce((a,c)=>({[c]:a}), [1, 2]);

console.log(foo);

1

You can create a function which takes three parameters:

  • The object on which keys will be added.
  • The array of keys in order.
  • The value which will be set to the last level.

Use forEach loop to loop though the keys. Except for last index add empty {} to the key. And change the current object to that empty object.

let foo = {}

function nestedKey(obj,keys,value){
  keys.forEach((x,i) => {
    obj[x] = i === keys.length -1 ? value : {};
    obj = obj[x]
  })
}
nestedKey(foo,['a','b','c'],[1,2]);

console.log(foo)

1

Try (improved Barmar answer without keys repetition)

let foo = {}, t;

const key1 = 'a';
const key2 = 'b';
const key3 = 'c';

t= foo[key1]= {};
t= t[key2]= {};
t[key3]= [1, 2];

console.log(foo);
If foo has more (nested) values they will be saved

Not the answer you're looking for? Browse other questions tagged or ask your own question.