4

Implementing a simple DataBase now.

The duplicate tag for this question is a bad judge, I think. The linked question does nothing for my requirement.

A user ID refer a user data, and I have 2 options to do that as follows: DB1 or DB2,

var DB1 = {
    user: {}
};
var DB2 = {
    user: []
};

DB1.user['001'] = {
    email: 'name@email.com',
    name: 'ken'
};
DB2.user['001'] = {
    email: 'name@email.com',
    name: 'ken'
};

console.log(DB1.user['001']);
console.log(DB2.user['001']);

The both DB1 and DB2 behaves as expected exactly in the same way, at least it appears so to me.

Is there any difference? Is just a way to express {} or []?

If different which one is more efficient?

Thanks for your thought.

UPDATE:

Thank you very much for all who kindly give me answers in detail.

I probably understand in this case, the array [] for associative manner is actually an object.

In this case, it behaves the same (as the object not array), fine I know that.

So, what I would like to know is , in this case, is it just a difference of the expression [] and {}.

More importantly, in this case, if it's not only the expression, how different and which one is more efficient, that's what I would like to know. Thank you.

UPDATE2:

Ok, this is not that obvious as many people thought. I've wrote a test code as follows:

var DB1 = {
    user:
    {}
};
var DB2 = {
    user: []
};
var DB3 = {
    user: []
};

for (var i = 0; i < 100000; i++)
{
    var id = ('0000' + i)
        .slice(-5);

    DB1.user[id] = {
        email: 'name@email.com',
        name: 'ken'
    };

    DB2.user[id] = {
        email: 'name@email.com',
        name: 'ken'
    };

    DB3.user[i] = {
        email: 'name@email.com',
        name: 'ken'
    };

}
//confirm the value just in case
console.log(DB1.user['00000']);
console.log(DB1.user['00001']);
console.log(DB1.user['99999']);
console.log(DB1.user['100000']);

for (var t = 0; t < 10; t++)
{
    console.log('-----------test ' + t);
    console.time('DB1');
    for (var i = 0; i < 100000; i++)
    {
        var id = ('0000' + i)
            .slice(-5);

        var data = DB1.user[id];
    }
    console.timeEnd('DB1');

    console.time('DB2');
    for (var i = 0; i < 100000; i++)
    {
        var id = ('0000' + i)
            .slice(-5);

        var data = DB2.user[id];
    }
    console.timeEnd('DB2');


    console.time('DB3');
    for (var i = 0; i < 100000; i++)
    {
        var id = ('0000' + i)
            .slice(-5);

        var id1 = id * 1;
        var data = DB3.user[id1];
    }
    console.timeEnd('DB3');
}

Result:

{ email: 'name@email.com', name: 'ken' }
{ email: 'name@email.com', name: 'ken' }
{ email: 'name@email.com', name: 'ken' }
undefined

-----------test 0
DB1: 46ms
DB2: 68ms
DB3: 28ms
-----------test 1
DB1: 39ms
DB2: 33ms
DB3: 26ms
-----------test 2
DB1: 32ms
DB2: 39ms
DB3: 25ms
-----------test 3
DB1: 57ms
DB2: 33ms
DB3: 27ms
-----------test 4
DB1: 39ms
DB2: 35ms
DB3: 27ms
-----------test 5
DB1: 39ms
DB2: 32ms
DB3: 27ms
-----------test 6
DB1: 33ms
DB2: 36ms
DB3: 26ms
-----------test 7
DB1: 39ms
DB2: 41ms
DB3: 40ms
-----------test 8
DB1: 32ms
DB2: 32ms
DB3: 28ms
-----------test 9
DB1: 36ms
DB2: 31ms
DB3: 28ms

For 100000 records, the array DB is slightly faster, but I think I will use Associative array style Object DB.

  • 3
    There are no associative arrays in JS. They're objects. – DanMan Feb 23 '14 at 13:24
  • possible duplicate of [Objects vs arrays in Javascript for key/value pairs](http://stackoverflow.com/q/688097/1169798) – Sirko Feb 23 '14 at 13:25
  • 1
    `{}` is more efficient. `[]` is an Array, which has all the Object-y goodness *plus* Array functionality. – reergymerej Feb 23 '14 at 13:47
  • 1
    I see you didn't get any answer with regards to what you were actually asking about efficiency - in regards to efficiency, the v8 JavaScript engine actually does the opposite and treats every objects as an array too! Each objects have a key/value store _and_ an array store where they store numbered properties, so both objects and arrays can store array values _as efficiently_ in Chrome/Node given the arrays are not sparse (that is, the indexes are numeric and sequential). As a side note - your benchmarks are incorrect, you should consider reading about how to time code. – Benjamin Gruenbaum Mar 06 '14 at 03:18

4 Answers4

7

[] is an array literal; it's equivalent to new Array().

{} is an object literal; it's equivalent to new Object().

You should only use arrays if you're actually storing an array of items; otherwise, use objects.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • Thanks, I know it's the literal for each of Array and Object. What I would like to know is the difference in this case. Can you tell me why should I only use array for this ? –  Feb 23 '14 at 13:25
  • I am very sorry to have found no one here properly answered which 'expression' is more efficient in this case. Again, I understand the Array/Object mechanism here. Is the efficiency the same in both DB1 and DB2 or different. Yes and No Question at least. Thanks. –  Feb 23 '14 at 13:54
6

The both DB1 and DB2 behaves as expected exactly in the same way, at least it appears so to me.

Not quite. [] creates an array, {} creates an object. In JavaScript, standard arrays aren't really arrays at all, they're just objects with some special behavior. You can add properties to those objects that aren't array entries, just like you can any other object. In your example, you're not using the array as an array, so both work, but if you were using the array as an array (using array indexes, length, push, splice, etc.), only the [] version would work as only that gives you an array.

Use an array when you need the features of an array. Use an object when you just need to map names to values. If using an array, be sure to use genuine array indexes, not non-index property names like '001'. (Details on that below.)

Here's an example of how you're not using the array as an array:

DB1.user['001'] = ...;

That does not create an array entry. Proof:

var a = [];
a['001'] = "foo";
console.log(a.length); // 0

It creates a property on the object with the name "001", but that property is not an array entry. In contrast:

a[1] = "foo";

or

a['1'] = "foo";

...creates an array entry:

var a = [];
a[1] = "foo";
console.log(a.length); // 2 (see below)

Why the difference? Again, standard arrays are just objects with special behavior. One of the key bits of special behavior relates to a certain class of property names, specifically those that are all digits in normal numeric form (no leading zeros) (they're still strings, even though we act like they're numbers). A property with a name in standard numeric form (and within range, they're allowed to be 0 through 232-2, inclusive) is an array entry.


I keep saying "standard arrays" because JavaScript is getting typed arrays (in fact, they're already in most engines):

var a = new Int32Array(10);

Typed arrays are actual arrays, completely unlike the [] "arrays".


Side note: Why was the length 2 here?

var a = [];
a[1] = "foo";
console.log(a.length); // 2

Because JavaScript arrays, by their nature, are sparse, and one of the special behaviors I was talking about is that when you add a property to an array that fits the definition of an array entry, length is set to the value one greater than the highest-numbered array entry. So even though our a array has only one entry, its length is 2.


Further side note: Objects are not called "associative arrays" in JavaScript, that's primarily a PHP term for a very special data structure it has which is an ordered name/value map. In JavaScript, we call them "objects" (primarily), or sometimes "maps" or "dictionaries." They are unordered, unlike PHP's associative arrays.


More importantly, in this case, if it's not only the expression, how different and which one is more efficient, that's what I would like to know.

Since you're not using the array as an array, I'd expect the object version to be slightly more efficient, because engines will initially try to optimize based on your using an array as an array, and then fall back to the object behavior when you do things like your '001' property name. So probably use an object from the start.

But in general, JavaScript "efficiency" is a very difficult topic. What's efficient on one engine is not efficient on other engines. Even if you don't believe premature optimization is a waste of time in other realms, it really is with JavaScript. Obviously don't do dumb things, but in general, wait until a performance problem arises and then tackle that problem on the platform on which it arises (and then test the other platforms you support to make sure you haven't introduced a new problem there).

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @KenOKABE: I added a bit to the answer. Basically, use an array when you need array features. Use an object when you just need to map names to values. It's unclear from the question whether you need array features (`push`, `length`, etc.). If you do, use an array and proper array indexes (not `'001'`); if not, just use an object. – T.J. Crowder Feb 23 '14 at 13:40
  • I am very sorry to have found no one here properly answered which 'expression' is more efficient in this case. Again, I understand the Array/Object mechanism here. Is the efficiency the same in both DB1 and DB2 or different. Yes and No Question at least. Yes, I do need to use '001' not an index of array manner. Thanks. –  Feb 23 '14 at 13:55
  • @KenOKABE: *"I am very sorry to have found no one here properly answered which..."* There's no need to be rude. Your question didn't remotely give the impression you actually understood what JavaScript's standard arrays were like. On efficiency: I'd've thought it was obvious that if you're not using the array as an array, it would be better to use an object. Note added to the end for why. – T.J. Crowder Feb 23 '14 at 14:00
  • T.J. Crowder, Thanks for your thought again. I've wrote a test code for my needs and the result. Please refer. –  Feb 23 '14 at 14:38
2
user: {}

creates an object whereas

user: []

creates an array. Arrays inherit from Object, so you can add random properties like this

DB2.user['001'] = {..};

to an array. For example

var myArray = [];
myArray["js"] = "awesome";
myArray.push("a");
myArray.push("b");
console.log(myArray);          // [ 'a', 'b', js: 'awesome' ]
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • I am very sorry to have found no one here properly answered which 'expression' is more efficient in this case. Again, I understand the Array/Object mechanism here. Is the efficiency the same in both DB1 and DB2 or different. Yes and No Question at least. Yes, I do need to use '001' not an index of array manner. Thanks. –  Feb 23 '14 at 13:56
  • 1
    @KenOKABE If you know the keys already, it would be idiomatic to use an Object. But, if you want to maintain the order of the data, Array should be your choice. Accessing a value with a key, has the same performance in both of them, since Array reuses many of Object's methods internally. – thefourtheye Feb 23 '14 at 13:58
  • 1
    @thefourtheye: *"Accessing a value with a key, has the same performance in both of them, since Array reuses many of Object's methods internally."* Only if you're using non-index properties, like the OP's `'001'`. If you use the array as an array, using array indexes, some engines optimize that. – T.J. Crowder Feb 23 '14 at 14:05
  • Thanks for your thought again. I've wrote a test code for my needs and the result. Please refer. –  Feb 23 '14 at 14:38
0

The notation is the same, but you are creating different objects. [] is an Array, so you'll get all the Array methods in the prototype. {} is an Object, so you'll the the Object methods.

An Array is probably best for your scenario, as it ensures the order of its elements. There's no guarantee of the order of items in an Object.

If you care about the order, use Array [], otherwise use Object {}.

Efficiency Test

var i = 10000;
console.time('arr');
while (i--) {
    ([]);
}
console.timeEnd('arr');


i = 10000;
console.time('obj');
while (i--) {
    ({});
}
console.timeEnd('obj');

result

arr: 10.527ms
obj: 8.974ms

Community
  • 1
  • 1
reergymerej
  • 2,371
  • 2
  • 26
  • 32
  • I am very sorry to have found no one here properly answered which 'expression' is more efficient in this case. Again, I understand the Array/Object mechanism here. Is the efficiency the same in both DB1 and DB2 or different. Yes and No Question at least. Yes, I do need to use '001' not an index of array manner. Thanks. –  Feb 23 '14 at 13:56
  • @KenOKABE I added code to test the efficiency. Using `{}` is the more efficient expression. – reergymerej Feb 23 '14 at 14:02
  • 1
    @blurd Havn't you mistyped something in the answer... ? :) – thefourtheye Feb 23 '14 at 14:04
  • @KenOKABE I assumed you'd want Array for creating a database, since it keeps track of the order. If you *only* care about efficiency, Object is best. – reergymerej Feb 23 '14 at 14:05
  • @BenVoigt that's embarrassing. :\ Thanks. – reergymerej Feb 23 '14 at 14:21
  • Thanks for your thought again. I've wrote a test code for my needs and the result. Please refer. –  Feb 23 '14 at 14:39