2

I'm working with some people are are used to making "associative arrays" in JavaScript like this:

var arr = new Array();
arr.prop_1 = "asdf";

or

arr['prop 2'] = "1234";

It works just like an object because it is. for...in loops can be used and accessing the properties is fine using a dot or a square brace. the lack of native array methods seems not to be lamented. I find it sort of semantically irritating however. Maybe I'm being picky, but I want a good argument for arresting the use of this syntax, but I can't understand how to start. Any suggestions?

6
  • 1
    What syntax do you suggest?
    – Mike
    Nov 21, 2013 at 22:16
  • 5
    If you don't know why it's a bad idea, maybe your dislike of them is unfounded and it's time to open your mind. Nov 21, 2013 at 22:28
  • @Mike use the numerical indices of the array or go with an Object of key:value pairs.
    – 1252748
    Nov 21, 2013 at 22:28
  • 3
    @AndyLester, thomas raised valid concern questioning the method that is clearly wrong. I'm not sure where you're going with your comment. Nov 22, 2013 at 3:16
  • 1
    Yeah he'd be opening his mind to affixing a magic marker to a cheese grater basically. There's really not much point in doing this. Nov 22, 2013 at 4:34

4 Answers 4

9

Which do you think looks cleaner?

object = new Array();
object.prop1 = 1;
object.prop2 = 2;
object.prop3 = 3;

or

object = {
  prop1: 1,
  prop2: 2,
  prop3: 3
}

?

Also, if you do something like this:

if (object.length === undefined) object.length = 10
object.length // 0

Then object.length will still be 0, which is definitely not what you would expect. You might think this is just a fake example that will never come up in real life, but look at this:

words = 'You should join our club because it is a club'.split(' ')
obj = new Array()
words.forEach(function(x) {
  if (obj[x] === undefined) obj[x] = 0
  obj[x] ++
})
for (var x in obj) console.log(x, obj[x])

This will log:

You 1
should 1
join NaN // <-- oops
our 1
club 2
because 1
it 1
is 1
a 1

Alternatively, you could make an analogy to any other object, like a function:

object = function() {}
object.prop1 = 1;
// ...

Anyone could immediately tell you that that is wrong, and using an array is just as wrong.

1
  • This is great. The last point is somehow even more demonstrative of good practices than the first. Thanks!
    – 1252748
    Nov 21, 2013 at 22:33
7

That's not an associative array. That's an array object abused. It just works because arrays are also objects in JavaScript.

When you're doing arr.prop_1 = "asdf"; or arr['prop 2'] = "1234"; what you're actually doing is monkey patching an object.

People use objects as maps often - but that'll get fixed soon since ES6 (the new version of the standard JS is based on) has Map types.

When to use an Array

When you have sequential data - a list of numbers for example

When to use a map

When you want to store a key-value mapping.

1
  • I know it's not an associative array. I like the phrase array object abused. I think I'll take that. Thanks!
    – 1252748
    Nov 21, 2013 at 22:21
2

It works "like an object" because near everything in JS IS an object.

Observe the following legit but mostly completely pointless property assignments:

function doSomething(){};
doSomething.someProperty = 'bob';

6..someProperty = 'bob'; //(6). would have worked too

'bob'.someProperty = 'bob';

Any object can also have properties via bracket notation, which allows for property names not regularly allowed by regular JS var/property naming restrictions. This comes in very handy for doing things like mapping URLs to methods or objects.

In your friends' case, there are two things they're doing that are kind of silly.

  1. They're using the Array constructor when they should be using an array literal. It's not a huge deal but it creates pointless overhead and some warn that somebody could override the Array constructor func but that would be a really stupid thing to do that would get noticed in most code bases anyway. General convention if you need a JS array is to simply do this.

    var arrayFoo = [];

  2. It serves zero benefit to use an array for what they perceive to be associative array-like behavior because any object in JS can have properties assigned in this manner and arrays are objects too. Using an object literal makes intent more clear and you don't inherit all that array stuff you won't be using with your object properties set with bracket notation anyway.

    var nameValuePairs = {
        'someValue': 'bob',
        anotherValue: 'joe',
        'string properties are like bracket notation' : 'bar'
    };
    

And of course you can add as many more on as you want:

nameValuePairs['some other value'] = 'bob 2';

Note that it is not always bad behavior to tack properties on to features of JS that aren't normally referred to as objects. For instance function constructors frequently have properties set directly on them. This is similar to how you might put static methods on a class in Java or C#. For instance you create timestamps with new Date but you can also parse milliseconds into a date object with Date.parse. In the right circumstances it might make sense to put extra properties on an array too but I wouldn't make a habit of it.

JS really only has two data structures. {} and []. That might sound limited but given how flexible and fully-featured they are, there's really not much you can't do readily with a combination of the two. There's no need for associative arrays because object literals have that covered.

So to get them to stop I would tell them it makes their intentions unclear or worse, it makes them look like JS noobs.

2
  • There is nothing silly in using new Array or new Object. Using {} for new Object or [] for new Array is just a notation. It is certainly not #1 in the list.
    – Florian F
    Nov 22, 2014 at 12:05
  • 1
    I certainly wouldn't go through great effort to lambast the evils of using the Object and Array constructors over the literal expressions. In 8 years of sometimes frightfully stupid code bases I've never seen someone overwrite the Array or Object constructors and the performance benefit is negligible barring scenarios involving instantiation of massive amounts of arrays. But it's fewer keystrokes and you don't have to explain anything to the because-doug-crockford-said-so types on the team. Point #2 is more important but it's at least a little bit silly not to do it the easy way. Nov 22, 2014 at 18:01
2

Using Array object in this manner feels very, very wrong. It completely removes the benefits of Array class and adds no value whatsoever.

The whole point of using arrays is to.. well.. treat them like arrays. So you get access to goodies such as push, pop, shift, splice, sort, join, .length etc.

Just consider what happens when you add few properties to your array this way:

var test = new Array();
test.prop1 = 'hi';
test.prop2 = 'ho';
test.prop3 = 'ha';

test.length; // returns 0
test.join() // returns ""
test.pop() // returns undefined ... and so on

You completely obliterated the true function of an array.

Even looping through this monstrosity is not trivial, as you need to pass each property through hasOwnProperty to check if it is a property you set, or is it something coming from Array.prototype. - as Doorknob pointed out internal array properties are not visible.

I'm not even going to start with what happens when someone tries to assign a property called length on this object, etc.

Now, there is a right way to store properties like this, using a simple Object.

var test = {};
test.prop1 = 'hi';
test.prop2 = 'ho';
test.prop3 = 'ha';

Here, you can still loop through it retrieving the keys and values but most important part of this syntax and what it is often used for, is that you can look up value directly, without looping: test['prop1']. This is great, because you don't have to loop through big object/array to find the property you're looking for.

So once again - if you want to store bunch of values and treat them as an array where you can add/remove items easily and use .length to check number of elements etc - use Array class.

If you want to access item directly by the key, and you don't need any of the array functionality (think hashmap), use simple Object.

But for God's sake do not use Array class for your hashmap base.

5
  • Wrong, wrong, wrong. Even looping through this monstrosity is not trivial, as you need to pass each property through hasOwnProperty to check if it is a property you set, or is it something coming from Array.prototype. Wrong - the built-in array methods are set up to not be visible with for-in. most important part of this syntax and what it is often used for, is that you can look up value directly, without looping: test['prop1'] you can do this with the Array() syntax too...
    – Doorknob
    Nov 24, 2013 at 14:52
  • @Doorknob You're right about the array props - they're obviously not visible in the loop, thanks for that. With the second one - yes, but that's not the point. Even thought array methods are not available in for loop, you can still get and set them with, ex. array['push'] but why would you use it this way? It's just bad practice and doesn't offer you anything apart from confusion. Say I had var drinktypes = new Array(), and then set drinktypes['pop'] = 'cola'; . see, I just broke an array. There is absolutely no benefit to use Array in this manner as normal {} would do. Nov 25, 2013 at 6:36
  • Also to the second point, assuming array is used as it's supposed to be, to retrieve item from an array you have to provide index, not the key. If you don't know the index of your item, you can't retrieve it with a single lookup hence {} is best for storing properties this way. Nov 25, 2013 at 6:42
  • I think you're missing the point. They're not using it as an array at all.
    – Doorknob
    Nov 27, 2013 at 14:23
  • No, I get it, that's why I'm arguing that Array is just not the right object to start with if it doesn't offer any benefits. Nov 28, 2013 at 1:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.