Holly
Holly

Reputation: 7752

JavaScript items missing from Object I just created

I've created an object in JavaScript and for some reason it's not saving the 17th and 20th items in the object.

You can see what I mean with the below code, the 17th & 20th items are not logged to the console after I have added them.

Why is this, I must be missing something obvious. I'm creating the object as the values I put in it will be used as constants available throughout an AngularJS app.

  var foo = { 
    001: { id: 001, name: "foo bar"}, 
    002: { id: 002, name: "foo bar"}, 
    003: { id: 003, name: "foo bar"}, 
    004: { id: 004, name: "foo bar"}, 
    005: { id: 005, name: "foo bar"}, 
    006: { id: 006, name: "foo bar"}, 
    007: { id: 007, name: "foo bar"}, 
    008: { id: 008, name: "foo bar"}, 
    009: { id: 009, name: "foo bar"}, 
    010: { id: 010, name: "foo bar"},
    011: { id: 011, name: "foo bar"}, 
    012: { id: 012, name: "foo bar"}, 
    013: { id: 013, name: "foo bar"}, 
    014: { id: 014, name: "foo bar"}, 
    015: { id: 015, name: "foo bar"}, 
    016: { id: 016, name: "foo bar"}, 
    017: { id: 017, name: "foo bar"},
    018: { id: 018, name: "foo bar"}, 
    019: { id: 019, name: "foo bar"}, 
    020: { id: 020, name: "foo bar"}
  }
  console.log(foo);

Upvotes: 1

Views: 89

Answers (4)

alebianco
alebianco

Reputation: 2555

Because prefixing a number with a 0 tells the compiler (ie. browser) that the number is an octal and 017 = 15

so all your indexes and subject to an octal-to-decimal conversion while converted to string (note the "" in the log) and some will override

other numbers (like 019) are not valid octal values, so their value is kept in decimal form i think

Upvotes: 1

Shilly
Shilly

Reputation: 8589

I think it has something to do with numbers starting with 0 are interpreted as octal in javascript. So 017 = 15 and you just overwrite the record of 15.

If you put your key names as explicit strings, it works. Same for the inner 'id' key of each record. This is why I don't use object keys that start with a number, and use an array if each key is just an index.

 var foo = { 
    '001': { id: '001', name: "foo bar"}, 
    '002': { id: '002', name: "foo bar"}, 
    '003': { id: '003', name: "foo bar"}, 
    '004': { id: '004', name: "foo bar"}, 
    '005': { id: '005', name: "foo bar"}, 
    '006': { id: '006', name: "foo bar"}, 
    '007': { id: '007', name: "foo bar"}, 
    '008': { id: '008', name: "foo bar"}, 
    '009': { id: '009', name: "foo bar"}, 
    '010': { id: '010', name: "foo bar"},
    '011': { id: '011', name: "foo bar"}, 
    '012': { id: '012', name: "foo bar"}, 
    '013': { id: '013', name: "foo bar"}, 
    '014': { id: '014', name: "foo bar"}, 
    '015': { id: '015', name: "foo bar"}, 
    '016': { id: '016', name: "foo bar"}, 
    '017': { id: '017', name: "foo bar"},
    '018': { id: '018', name: "foo bar"}, 
    '019': { id: '019', name: "foo bar"}, 
    '020': { id: '020', name: "foo bar"}
  }
  console.log(JSON.stringify(foo));

Upvotes: 1

Mike Cluck
Mike Cluck

Reputation: 32511

That's because that isn't a valid format for decimal numbers. What's happening is you're writing octal numbers. Essentially, they're in base 8 instead of 10.

If you want them in base 10, remove the leading zeros.

var foo = { 
    1: { id: 1, name: "foo bar"}, 
    2: { id: 2, name: "foo bar"}, 
    3: { id: 3, name: "foo bar"}, 
    4: { id: 4, name: "foo bar"}, 
    5: { id: 5, name: "foo bar"}, 
    6: { id: 6, name: "foo bar"}, 
    7: { id: 7, name: "foo bar"}, 
    8: { id: 8, name: "foo bar"}, 
    9: { id: 9, name: "foo bar"}, 
    10: { id: 10, name: "foo bar"},
    11: { id: 11, name: "foo bar"}, 
    12: { id: 12, name: "foo bar"}, 
    13: { id: 13, name: "foo bar"}, 
    14: { id: 14, name: "foo bar"}, 
    15: { id: 15, name: "foo bar"}, 
    16: { id: 16, name: "foo bar"}, 
    17: { id: 17, name: "foo bar"},
    18: { id: 18, name: "foo bar"}, 
    19: { id: 19, name: "foo bar"}, 
    20: { id: 20, name: "foo bar"}
  }
  console.log(foo);

If you want the leading zeros, you need to use strings.

var foo = { 
    "001": { id: "001", name: "foo bar"}, 
    "002": { id: "002", name: "foo bar"}, 
    "003": { id: "003", name: "foo bar"}, 
    "004": { id: "004", name: "foo bar"}, 
    "005": { id: "005", name: "foo bar"}, 
    "006": { id: "006", name: "foo bar"}, 
    "007": { id: "007", name: "foo bar"}, 
    "008": { id: "008", name: "foo bar"}, 
    "009": { id: "009", name: "foo bar"}, 
    "010": { id: "010", name: "foo bar"},
    "011": { id: "011", name: "foo bar"}, 
    "012": { id: "012", name: "foo bar"}, 
    "013": { id: "013", name: "foo bar"}, 
    "014": { id: "014", name: "foo bar"}, 
    "015": { id: "015", name: "foo bar"}, 
    "016": { id: "016", name: "foo bar"}, 
    "017": { id: "017", name: "foo bar"},
    "018": { id: "018", name: "foo bar"}, 
    "019": { id: "019", name: "foo bar"}, 
    "020": { id: "020", name: "foo bar"}
  }
  console.log(foo);

Upvotes: 4

lonesomeday
lonesomeday

Reputation: 237905

The problem is that number literals in Javascript that begin with 0 are treated as an octal (i.e. base 8). So 020 === 16. If a number starts with a 0 but contains the digits 9 or 8 (i.e. it is an invalid octal number) it is treated as a normal decimal number.

So when you do 017 and 020, it is being treated as 15 and 16, so that property gets written to twice.

If you want numeric keys, you need to make them all in the same base, so lose the leading 0. If you want literally 020, then you need to make the keys and values strings:

"001": { id: "001", name: "foo bar"}

Upvotes: 5

Related Questions