Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding how javascript hashtables work

Tags:

javascript

Could anyone explain to me why the code sample below reports true? I would have assumed that like in C# the instance of Test1 != instance of Test2.

Update: So I think I will go with some unique identifier stored in the base of both Test1 and Test2.

function Test1() { };

function Test2() { };

var test1 = new Test1();

var test2 = new Test2();

var dict = new Array();

dict[test1] = true;

alert(dict[test2]);
like image 761
Oliver Weichhold Avatar asked Aug 19 '11 19:08

Oliver Weichhold


People also ask

How does hash work in JavaScript?

A hash function is a method or function that takes an item's key as an input, assigns a specific index to that key and returns the index whenever the key is looked up. This operation usually returns the same hash for a given key. A good hash function should be efficient to compute and uniformly distribute keys.

Are JavaScript objects Hashtables?

A JavaScript Object is an example of a Hash Table because data is represented a key/value pairs. A hashing function can be used to map the key to an index by taking an input of any size and returning a hash code identifier of a fixed size.

What is the purpose of Hashtables?

Hash tables let us implement things like phone books or dictionaries; in them, we store the association between a value (like a dictionary definition of the word "lamp") and its key (the word "lamp" itself). We can use hash tables to store, retrieve, and delete data uniquely based on their unique key.

How do Hashtables grow and shrink?

The usable size of a hash table is the number of associations that the table can hold at a given time. If the number of associations in the table exceeds the usable size, the table will automatically grow, increasing the usable size to a new value that is sufficient to hold the associations.


4 Answers

Your object (JavaScript's hashtable) is not using the instance of test1 or test2, but the string representation, as a key. Since both test1 and test2 have the same string representation: "[object Object]", the true value is associated with that key.

Try doing something like below instead:

function Test1(id) { this.id=id };

function Test2(id) { this.id=id };

var test1 = new Test1('1'); 
var test2 = new Test2('2'); 
var dict = {};

dict[test1.id] = true;

console.log(dict[test1.id]);
like image 62
Hyangelo Avatar answered Oct 17 '22 04:10

Hyangelo


Keys in 'hashtables' (objects, basically) are always strings. So anything you add will be converted to a string.

new Test1();

returns a instance of Test1. Converted as a string, this is:

"[object Object]"

The same goes for Test2. So in fact, when storing true under the key of new Test1() as a string, you are working with the exact same record as the one by obtaining with the key new Test2() as a string. In other words,

(new Test1()).toString() == (new Test2()).toString();

The actual object is therefore simply:

{
 "[object Object]": true
}

A solution is overwriting .toString() like this:

Test1.prototype.toString = function() { return "Test1" };
Test2.prototype.toString = function() { return "Test2" };

Then dict[test1] will be stored as dict['Test1'] and dict[test2] as dict['Test2'], which allows you to differ between them. Still, manually setting dict['Test1'] would overwrite things. As far as I know, there is no way to assign an object as a key.

like image 37
pimvdb Avatar answered Oct 17 '22 03:10

pimvdb


Javascript objects aren't exactly hashtables; they're actually objects with string keys.

When you use an object as a key, the object is converted to a string by calling toString().
toString() will return the same string for all custom classes (unless you create your own toString), so they end up using the same key.

like image 3
SLaks Avatar answered Oct 17 '22 03:10

SLaks


First: Use arrays only for numerical keys. For anything else use objects.

Property names can only be strings. Anything else is converted to its string representation. In case of objects, this is [object Object] or whatever toString() returns.

Which means, that if you want to make both objects distinguishable, you have to override this method and let it return something which is unique to each instance.

This question might help you: Hash/associative array using several objects as key

like image 2
Felix Kling Avatar answered Oct 17 '22 02:10

Felix Kling