3

I'm learning javascript and after reading a tutorial on how to initialize an object, I found the following example:

var obj = {  property_1: value_1,   // property_# may be an identifier...
                      2: value_2,   // or a number...
                                    // ...,
           "property n": value_n }; // or a string

My doubt is in the property with a number as a name. I understand this, but I can't find a real benefice of using it. I read this question and, from my point of view, this kind of notation could lead to bad design or an unnecessary complexity in my code, so I would like to know why this syntax exist.

Do this kind of declaration is used frequently? In what kind of scenarios this could be an ideal alternative?

dsh
  • 12,037
  • 3
  • 33
  • 51
Alex S. Diaz
  • 2,637
  • 2
  • 23
  • 35
  • 4
    There is no particular benefit. It looks like the code was written that way simply to demonstrate different valid property names in an object literal. – Jordan Running Nov 05 '15 at 18:02
  • 3
    That's terrible code that's typically written by people who don't know what arrays are. Run from it like fire. Sadly it's used pretty frequently. – Benjamin Gruenbaum Nov 05 '15 at 18:03
  • 6
    Its usefull in any scenario where you would need a HashMap functionality with ID's as keys – xjedam Nov 05 '15 at 18:05
  • 1
    @xjedam if you want a map use a `Map`. – Benjamin Gruenbaum Nov 05 '15 at 18:06
  • 1
    @Benjamin Map is not fully supported in all browsers I think – xjedam Nov 05 '15 at 18:09
  • @BenjaminGruenbaum you could use an _Object_ as the `iterable` in `new Map(iterable)` – Paul S. Nov 05 '15 at 18:13
  • @PaulS.: Objects are not iterable (by default), they're only enumerable. You'd need `new Map(Reflect.enumerate(obj))` – Bergi Nov 05 '15 at 18:28
  • @Bergi The following will work in _Google Chrome_ (though it's _very very_ unlikely you'd ever write something like it in practice) `new Map(Object.assign(Object.create(Array.prototype), {0: ['foo', 'bar'], length: 1}))`, i.e. this is an _Object_, `new Map` is accepting it – Paul S. Nov 05 '15 at 18:51
  • 1
    @PaulS.: He, an object that inherits `Symbol.iterator` from `Array.prototype` can hardly be called "default" :-) Of course even `[]` is an object as well, but that's not what I meant. – Bergi Nov 05 '15 at 18:53

3 Answers3

1

Arrays

JavaScript arrays are objects where some of the keys are integers(*).

[9, 8, 7] is similar to an object { 0: 9, 1: 8, 2: 7 }.

The main difference is that the array has a prototype of Array.prototype instead of Object.prototype.

(*) As Benjamin Gruenbaum points out, the array keys are coercible to UInt32. Keys of objects are always either strings or symbols. And as djechlin points out, arrays are allowed to have properties with any kind of key, but I do not recommend adding your own non-integer keys on an array.

Arguments

An array-like object called arguments is available within any function (*). Each argument received by the function will be a property on arguments, with an integer-like key.

In the following code, the example call returns an object like { 0: 9, 1: 8, 2: 7, length: 3 }.

function example(a, b, c) {
    return arguments;
}
example(9, 8, 7);

(*) In modern JavaScript, there is no arguments object in arrow functions.

Keen
  • 954
  • 12
  • 19
  • 4
    *Where the keys are coercible to UInt32. The keys of objects are always either strings or symbols. – Benjamin Gruenbaum Nov 05 '15 at 18:04
  • 3
    `var foo = []; foo.chicken = 'chicken'` - keys are not necessarily integers. – djechlin Nov 05 '15 at 18:12
  • And `length` is of course a property with key `length`, which is not an integer. – djechlin Nov 05 '15 at 18:15
  • I would say the main difference between `[9,8,7]` and `{0: 9, 1:8, 2:7}` is that the former is an `Array`. it has methods such as `map` for instance that the object does not. – djechlin Nov 05 '15 at 18:16
  • @djechlin I see your non-integer property name _length_ and raise you a _splice_ to make it pretty in the console – Paul S. Nov 05 '15 at 18:17
  • `var foo = []; foo[-3] = 2;` is an array with highest integer index `-3` but its length is 0, not -2. – djechlin Nov 05 '15 at 18:17
  • While all these comments are true, you _can_ use non.integer keys in an array, using integer keys in an object feels somehow OK whereas using string keys in an array really doesn't. Given that assumptions are often made (when looping for example) for arrays based on the value of the `length` property, I be happy to use an object with only integer keys but would rrecommend against abusing arrays in this fashion. – Adam Nov 05 '15 at 18:23
  • `var foo = []; foo[100000000000000]= 3;` gives `foo.length` as 0, not 100000000000001. – djechlin Nov 05 '15 at 18:25
  • `var foo = []; foo.length = 12;` gives length as 12, not 0. – djechlin Nov 05 '15 at 18:27
  • @djechlin Okay, I guess I won't try to summarize the behavior of `length` here, since it's not relevant enough to be worthwhile. – Keen Nov 05 '15 at 18:30
  • yeah a bit but pretty much everything in your answer is inaccurate. I would have been happy with "Arrays are examples of objects that use numbers as keys" but the rest of your explanation is problematic. Arrays are indeed a good example of objects that use numbers as keys but then you describe the difference between arrays and objects -- inaccurately, and exclude arraylike objects (such as `arguments`) in the process. – djechlin Nov 05 '15 at 18:31
  • `arguments` is probably the best example of a non-array object that uses integer-like keys. Yes, I should add that example too. – Keen Nov 05 '15 at 18:35
  • @djechlin There is a difference between _Arrays_ and _Objects_? _Arrays_ are a subset of the set of all _Objects_. – Paul S. Nov 05 '15 at 18:45
  • @PaulS. yes, I mentioned that "arrays are examples of objects" twice in my last comment. If you're concerned with, if something is a subset of something else, is there a difference between those two things, that's purely semantic. – djechlin Nov 05 '15 at 18:51
  • well, arrays keys are actually strings, just to throw a wrench into yall's petty argument... the main diff between arrays and objects is the auto-computed length property and the prototype methods. arrays can be sparse, and at least in V8, it's not wasteful to use sparse arrays. – dandavis Nov 05 '15 at 19:38
1

Using integers as object keys is useful when creating sparse arrays and matrices, for instance mapping a 1000 element vector with 0 everywhere except the 10th element as

v = {10: 1}

JS arrays cannot be used here since you need to be able to specify the element position using the key.

In ECMAscript 6 using [Map]1 is better since it is actually made to be a mapping, but in codebases based on older ES standards, you would probably still see object being used for mappings like these.

Simon Thordal
  • 893
  • 10
  • 28
  • Well you can use sparse arrays as well, but I guess you meant for serialisation, right? `[,,,,,,,,,1]` is not super sexy – Bergi Nov 05 '15 at 18:30
  • I was more thinking of if you wanted to implement a sparse matrix multiplication function for instance. If you use a sparse array and multiply each element by 3 it will still attempt to perform the multiplication on unassigned elements. – Simon Thordal Nov 05 '15 at 18:40
  • 1
    Well that would be one of the few cases where you could use a `for in` loop on an array as well (or `Object.keys`, for that matter), if sparse iteration is what you are looking for. But yes, the difference between a sparse array and an integer-keyed object is negligible – Bergi Nov 05 '15 at 18:46
0

That code is contrived to make the point. But, since you asked for an example where it could be used, let me give you a couple.

  • It can happen that if you receive JSON formatted data it will be like this. Depends on details of the external system.

  • Another might be for consistency. E.g. suppose you had a data model from which you would generate your HTML. It might be that is uses objects for the possible values for each field (assuming the field can only take one of a number of possible values). These fields could then be rendered as radio buttons or as a select. Some of these fields will use strings as possible values, so the natural thing is tyo make the possible values list into an object. But some will use integer keys - still probably better to stick to the list always being an object.

E.g.

var prio_field_pos_vals = {
  0: 'Show Stopper',
  1: 'Urgent',
  2: 'High',
  3: 'Low' 
}

Of course, this would probably not be defined as a standalone variable but as part of a model, but you get the idea. I would avoid integer keys (and keys with spaces in the string) for objects unless you have a reason for them, but when you have a reason, use them.

Adam
  • 6,539
  • 3
  • 39
  • 65
  • Of course JSON will always have quotes around keys, so rather `{"0":"…", …}` – Bergi Nov 05 '15 at 18:32
  • On unordered object might not be the best fit for a list of radio buttons. An array of `{value: …, text: …, …}` records might be a better idea – Bergi Nov 05 '15 at 18:32
  • Yes, if it came as JSON data (most liekly) it would have quotes. Depends on how it is generated though. Both valid in javascript as far as I am aware. – Adam Nov 05 '15 at 18:37