5

Say I have an object such as this:

var time = {
    'second': 1000,
    'minute': 1000 * 60,
    'hour'  : 1000 * 60 * 60,
    'day'   : 1000 * 60 * 60 * 24,
    'week'  : 1000 * 60 * 60 * 24 * 7
};

How would I shorten it so it would reference the other keys?

I mean something like this:

var time = {
    'second': 1000,
    'minute': this.second * 60,
    'hour'  : this.minute * 60,
    'day'   : this.hour   * 24,
    'week'  : this.day    * 7
}

I can't reference each using time.foo because the variable isn't initialized yet. I could simply add each on a new command, such as time['hour'] = time.minute * 60;, but I'd rather do it in one command.

Tgwizman
  • 1,469
  • 2
  • 19
  • 34
  • This cannont be done with a single Object Literal.. There are a number of duplicates, but finding them can be a PITA sometimes. –  Sep 12 '12 at 21:45
  • 3
    FYI, your code is probably more readable if you keep the code from your first example; possibly with `60 * 60` written as `3600` (everyone knows that's an hour). – ThiefMaster Sep 12 '12 at 21:47
  • 1
    Similar: http://stackoverflow.com/questions/4616202/self-references-in-object-literal-declarations , http://stackoverflow.com/questions/7433395/object-referencing-its-own-property-on-initilization?lq=1 , http://stackoverflow.com/questions/2787245/how-can-a-javascript-object-refer-to-values-in-itself?rq=1 –  Sep 12 '12 at 21:48
  • Also similar: http://stackoverflow.com/q/4858931/615754 – nnnnnn Sep 12 '12 at 21:50
  • @pst Thanks for pointing that out. I actually had trouble on finding one like the question I had. I have no idea what to search for when looking for a duplicate to this question, considering I just couldn't find the right words to describe what I was going for (hence the long title). – Tgwizman Sep 12 '12 at 21:58

5 Answers5

6

you can't reference properties from itself if you are declaring it like that as the properties dont yet exist, you might want to try a different approach

var time = {};
time.second = 1000;
time.minute = time.second * 60;
...
rroche
  • 1,262
  • 1
  • 13
  • 29
5
var time = (function(){
    var second = 1000,
        minute = second * 60,
        hour = minute * 60,
        day = hour * 24,
        week = day * 7;
    return {
        'second': second,
        'minute': minute,
        'hour'  : hour,
        'day'   : day,
        'week'  : week
    };
})();

UPD

Even shorter:

var time = (function(){
    var w, d, h, m, s;
    w = (d = (h = (m = (s = 1000) * 60) * 60) * 24) * 7;
    return {
        second: s,
        minute: m,
        hour  : h,
        day   : d,
        week  : w
    };
})();

And finally the minified version of this:

var time=function(){var a,b,c,d,e;a=(b=(c=(d=(e=1e3)*60)*60)*24)*7;return{second:e,minute:d,hour:c,day:b,week:a}}()
dyurkavets
  • 416
  • 3
  • 5
  • I really loved the way you posted the answer for my question. I made yours the answer. If I'm not mistaken, you should get a badge from having your answer being chosen on an oldish post. – Tgwizman Nov 10 '13 at 02:18
3

You can't do this as the object does not exist yet while it's parsed.

The only way to avoid this is creating an object and then adding the keys one by one - so you already have an object which has the properties you want to re-use.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
3

Change the object to a constructor function and you can do this:

function Time() {
    this.second = 1000;
    this.minute = this.second * 60;
    this.hour = this.minute * 60;
    this.day = this.hour * 24;
    this.week = this.day * 7;
}

// Use
var time = new Time();
Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • No need for a constructor. Just create the object with `var obj = {}` and then assign the values. At least the object in the question does not look like something that is likely to be re-used. – ThiefMaster Sep 12 '12 at 21:46
  • @ThiefMaster - you are absolutely correct - this is not the *best* way to create a "constant". However, it is nicely readable and if it is wrapped in an IIFE as frontendmagic did in his answer then the only available value *is* an instance (which may be treated as a constant). – Sean Vieira Sep 12 '12 at 21:54
2

You can use the getters syntax supported by most modern browser :

var time = {
    'second': 1000,
     get minute () {
       return this.second * 60;
     },
     get hour (){
       return this.minute * 60;
     },
     get day (){
       return this.hour * 24;
     },
     get week (){
       return this.day * 7;
     }
};
Gomino
  • 12,127
  • 4
  • 40
  • 49