0

I know this is very basic, but why does x return undefined in this code block? Is there a way to define a property and immediately use it to set another property?

    var grid = {
        x : 75,
        y : 75,
        location : [grid.x, grid.y],                
        init : function () {
            console.log(grid.location[0]);
        }
    }
worked
  • 5,762
  • 5
  • 54
  • 79
  • if you need to support IE8 or < then you can do something like: `location: function() { return [this.x, this.y] },`. same for init. Then to call it outside of grid, you use `grid.location()` – Jeff Shaver Mar 25 '13 at 14:45

2 Answers2

2

You can't use the variable to access properties of the object before the object has been assigned to the variable. While the object is created, the variable grid is still undefined. While the object is being created, you don't have any reference to it.

You can use the properies once the object has been assigned to the variable:

var grid = {
    x : 75,
    y : 75,
    init : function () {
        console.log(grid.location[0]);
    }
}

grid.location = [grid.x, grid.y];

You can also wrap this in a function expression to get code that returns the complete object:

var grid =
  (function(){

    var obj = {
      x : 75,
      y : 75,
      init : function () {
        console.log(grid.location[0]);
      }
    };
    obj.location = [obj.x, obj.y];

    return obj;

  })();
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • In your first example, why don't you put `this.location = [this.x, this.y];` into the `.init()` method instead of calling it manually from outside the object? – insertusernamehere Mar 25 '13 at 15:00
  • @insertusernamehere: That's one option, but it would only work if the `location` property is only accessed inside the `init` method, or only accessed after `init` has been called. Also it would reassign the property if `init` was called more than once, and that might not be desirable. – Guffa Mar 25 '13 at 15:15
  • True that. I thought that there was some other magic I'm overlooking. :) In this case I think that the `.init()`-method will act like some sort of constructor and will be called only once. – insertusernamehere Mar 25 '13 at 15:26
  • @Guffa: I set my location array inside the init function as it's only accessed after init has been called. Big ups to all these great responses. – worked Mar 25 '13 at 18:17
1

Is there a way to define a property and immediately use it to set another property?

No. However, you can use a getter, which is more-or-less syntactic sugar for a function:

var grid = {
    x : 75,
    y : 75,
    get location() {
        return [this.x, this.y];
    },                
    init : function () {
        console.log(grid.location[0]);
    }
}

http://jsfiddle.net/mattball/erUJj

This answer sums up the various options: https://stackoverflow.com/a/15486618

Community
  • 1
  • 1
Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • 1
    Note: This is not supported in IE8. – Guffa Mar 25 '13 at 14:31
  • @JeffShaver I strongly advise that you read the documentation linked in my answer. https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/get – Matt Ball Mar 25 '13 at 14:33
  • @MattBall however, according to your linked documentation, this isn't compatible with IE until version 9 as Guffa said. – Jeff Shaver Mar 25 '13 at 14:40
  • @JeffShaver that's true. My linked answer and Guffa's comment both said as much. – Matt Ball Mar 25 '13 at 14:45
  • 1
    Note also that this changes the behaviour, as the property returns a new array with the current values each time it's used, instead of assigning a copy of the values when the object is created. – Guffa Mar 25 '13 at 15:19