1

While I understand that the following structure will not maintain order if iterated upon, I don't understand why the id++ works. I would think that incrementing the id is dependent on a structure that maintains order like an array. How is it smart enough to increment? I can't find the documentation. Please help.

let id = 0;
const cars = {
    "ford": {
        "model": "focus",
        "id": id++
    },
    "honda": {
        "model": "civic",
        "id": id++
    },
    "toyota": {
        "model": "corolla",
        "id": id++
    }
}
console.log(cars);
{ 
    ford: { model: 'focus', id: 0 },
    honda: { model: 'civic', id: 1 },
    toyota: { model: 'corolla', id: 2 } 
}
phil o.O
  • 406
  • 2
  • 4
  • 20
  • 2
    I would never recommend doing this. It's "smart" enough to increment because it happens to evaluate the expressions in the order they appear, but it's confusing and could lead to nasty surprises (if, for example, you copy the code somewhere else). – itdoesntwork Jun 04 '18 at 17:37
  • @SudhanshuVishnoi I think this is somewhat more subtle- it's the order of evaluation of object property values, not the internal order they're stored in. – itdoesntwork Jun 04 '18 at 17:37
  • @itdoesntwork maybe this then: https://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop ;) – Sid Vishnoi Jun 04 '18 at 17:39
  • 2
    @SudhanshuVishnoi still different. The question here doesn't deal with looping, but rather the order of evaluation of the components of the object _literal_. – itdoesntwork Jun 04 '18 at 17:40
  • You are making an implicit assumption that property values are evaluated in the order they appear. *"I would think that incrementing the id is dependent on a structure that maintains order like an array."* Element order at runtime and evaluation order are two different things. – Felix Kling Jun 04 '18 at 17:41
  • ah. my bad. but wouldn't order of looping be same as order of evaluation? – Sid Vishnoi Jun 04 '18 at 17:41
  • 2
    @SudhanshuVishnoi: No. Example: `let id = 0; let obj = {foo: id++, 42: id++}; for (const prop in obj) { console.log(prop, obj[prop]); }` – Felix Kling Jun 04 '18 at 17:41
  • 1
    @SudhanshuVishnoi Not necessarily, as JS provides no guarantee of the order of properties in an object during looping. The order in which they appear in the code, therefore, technically has no bearing on the order in which they are visited in a loop. (However, you may observe that some implementations respect this order). – itdoesntwork Jun 04 '18 at 17:42
  • @FelixKling yep, hence my confusion. – phil o.O Jun 04 '18 at 17:44
  • @itdoesntwork see that's what I was thinking, throw the properties in an array and then iterate over them. I literally couldn't think of the terms order of evaluation and order of looping. They were on the tip of my tongue. – phil o.O Jun 04 '18 at 17:44
  • 1
    @SudhanshuVishnoi: Think about a generic hash table implementations. The hash of the key determines the position in the table. That order is likely very different from the order the keys are written in the source code. – Felix Kling Jun 04 '18 at 17:45
  • @itdoesntwork developers blindly copying code. Noooo. That won't ever happen. :) – phil o.O Jun 04 '18 at 17:55

1 Answers1

1

Object literals are evaluated in order of source appearance, much like every other JS code. So the expression for the first property value is always evaluated before the second property value.

This order of initialisation has nothing to do with the order in which the properties of the object can be enumerated later, which - as you noted - is not necessarily the same.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375