166

My code:

var a = "1",
b = "hello",
c = { "100" : "some important data" },
d = {};

d[a]["greeting"] = b;
d[a]["data"] = c;

console.debug (d);

I get the following error:

Uncaught TypeError: Cannot set property 'greeting' of undefined.

I'm trying to do something similar to an associative array. Why isn't this working?

fiza khan
  • 1,280
  • 13
  • 24
StackOverflowNewbie
  • 39,403
  • 111
  • 277
  • 441

8 Answers8

231

you never set d[a] to any value.

Because of this, d[a] evaluates to undefined, and you can't set properties on undefined.

If you add d[a] = {} right after d = {} things should work as expected.

Alternatively, you could use an object initializer:

d[a] = {
    greetings: b,
    data: c
};

Or you could set all the properties of d in an anonymous function instance:

d = new function () {
    this[a] = {
        greetings: b,
        data: c
    };
};

If you're in an environment that supports ES2015 features, you can use computed property names:

d = {
  [a]: {
    greetings: b,
    data: c
  }
};
zzzzBov
  • 174,988
  • 54
  • 320
  • 367
40

You have to set d[a] to either an associative array, or an object:

  • d[a] = [];
  • d[a] = {};

Without setting, this is what's happening:

d[a] == undefined, so you're doing undefined['greeting']=b; and by definition, undefined has no properties. Thus, the error you received.

vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • `array` or `object`. JS doesn't have associative arrays, though `Object` can act like one for limited uses. – Jeremy J Starcher Sep 18 '12 at 18:39
  • @JeremyJStarcher: absolutely correct and important to know, but by that level of thinking, JavaScript has no arrays; it only has objects – vol7ron Sep 19 '12 at 00:29
  • Not exactly. There are aspects of associative arrays that are not true about Javacript objects that can trip up coders. (True associate arrays aren[t limited by requiring keys to be strings. The presence of inherited predefined properties is another major difference.) On the other hand, Javascript arrays, while objects, act like one expects a numerical array to behave. One is an aspect of functionality, while the other is internal implementation. – Jeremy J Starcher Sep 19 '12 at 00:35
8

The object stored at d[a] has not been set to anything. Thus, d[a] evaluates to undefined. You can't assign a property to undefined :). You need to assign an object or array to d[a]:

d[a] = [];
d[a]["greeting"] = b;

console.debug(d);
DigitalZebra
  • 39,494
  • 39
  • 114
  • 146
  • 2
    Best to assign an object: `d[a] = {};` - using arrays with non-numeric keys tends to lead to problems down the line. – nnnnnn Sep 20 '11 at 03:58
6

In ES6 you can use the spread operator, if d[a] is undefined it will just ignore, but if it has content it will keep it

d[a] = { ...d[a], greeting: b, data: c };

The accepted answer will override anything in d, which is not the behaviour we would always want

Shadoweb
  • 5,812
  • 1
  • 42
  • 55
5

i'd just do a simple check to see if d[a] exists and if not initialize it...

var a = "1",
    b = "hello",
    c = { "100" : "some important data" },
    d = {};

    if (d[a] === undefined) {
        d[a] = {}
    };
    d[a]["greeting"] = b;
    d[a]["data"] = c;

    console.debug (d);
iohzrd
  • 113
  • 2
  • 3
5

In javascript almost everything is an object, null and undefined are exception.

Instances of Array is an object. so you can set property of an array, for the same reason,you can't set property of a undefined, because its NOT an object

wukong
  • 2,430
  • 2
  • 26
  • 33
1

d = {} is an empty object right now.

And d[a] is also an empty object.

It does not have any key values. So you should initialize the key values to this.

d[a] = {
greetings:'',
data:''
}
Nikhil Yadav
  • 1,419
  • 1
  • 13
  • 8
1

This occurs due to setting value to an object property without properly defining it's structure.

eg: The following code will give such error, because we are assigning value to an array. That can't be possible.

let boatNames = [];
 boats.map(boat => {
    while( i < boats.length){
      boatNames[i].name = boat.boat.name;
      i++;
    }
  })

To make it work, before setting some value to a property (boatNames[i].name = boat.boat.name;) make sure you define it first. like this... boatNames[i] = {};

navinrangar
  • 904
  • 10
  • 20