0

I am declaring this object:

var layout = {
    menu: {
        type: 0,
        x: 50,
        y: 50,
        w: 50,
        h: 50
    },

    name: {
        type: 2,
        str: "name",
        x: 50+layout.menu.x,
        y: 40+layout.menu.y,
        h: 25
    }
}

But for some reason, when trying to reference "layout.menu", the console screams that it is undefined, when it is clearly defined just before it. Could anyone shed some light on why this is happening?

Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122

2 Answers2

1

The variable layout only receives its value when the right part of the assignment has been evaluated first. Only after that evaluation the assignment to layout takes place. The whole object literal (until the end of the code you quoted) needs to be evaluated. Before the assignment takes place, even during the valuation of the object literal, the variable layout will still be undefined. Hence any reference to it in the object literal will be undefined.

To solve this, use an incremental approach:

var layout = {
    menu: {
        type: 0,
        x: 50,
        y: 50,
        w: 50,
        h: 50
    }
};
// At this moment layout has a value with the "menu" property. So we continue:
layout.name = {
    type: 2,
    str: "name",
    x: 50+layout.menu.x,
    y: 40+layout.menu.y,
    h: 25
};

If you were intending to have a live reference to the values of menu.x and menu.y, so that any update of those property would immediately reflect inside the name structure, then you need a function, which could be a getter:

var layout = {
    menu: {
        type: 0,
        x: 50,
        y: 50,
        w: 50,
        h: 50
    },
    name: {
        type: 2,
        str: "name",
        get x() { return 50+layout.menu.x },
        get y() { return 40+layout.menu.y },
        h: 25
    }
};

// Demo
console.log(layout.name.x);

But this is not advisable as a solution if you only wanted to solve your initial reference problem, because with this solution every time you read the value of layout.name.x, the getter function is executed, which is unnecessary overhead.

trincot
  • 317,000
  • 35
  • 244
  • 286
0

You are calling menu before the object created with literal is actually assigned to the variable layout.

You can add menu and name properties one by one.

var layout = {};
 layout.menu = ...
 layout.name = ...
Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122