2

I couldn't find more information on this but as far as I understand has method from Map and Set collections determines whether a given map or set has an object by checking for reference equality. But I'd like to check whether the objects are equal by comparing their properties.

For example:

let map = new Map();
let obj = {name: "Jack"};
map.set(obj, "myObj");
let result = map.has({name: "Jack"}); //false

result is false but the properties of the objects are identical, so in such case I'd like has to return true.

In Java I'd have to override equals and hashCode methods inside my class to achieve such functionality. Is there something similar I can do in Javascript without overriding has itself?

Yos
  • 1,276
  • 1
  • 20
  • 40
  • You either iterate the Map and compare one by one, or you store JSON strings of the objects, then `has` works as expected. – Jonas Wilms Apr 29 '18 at 11:52
  • @JonasW. thanks, but why is this question a duplicate? I'm asking about internals of `has` not about general comparison of two objects (which the question you linked discusses) – Yos Apr 29 '18 at 11:55
  • Jup, `has` uses equality internally, so the answers are the same – Jonas Wilms Apr 29 '18 at 11:55
  • @JonasW. "has uses equality internally" this should be the answer then. – Yos Apr 29 '18 at 11:56
  • 2
    Why not set map key as a string derived from unique values in the objects? – charlietfl Apr 29 '18 at 12:07

1 Answers1

2

but the properties of the objects are identical

Really? As this answer outlines, it is usually very hard to define the identity of an object, as it is built of much more than sinple key-value pairs. Therefore it is impossible to derive a unique hash for it to be used in a hashtable, thats why javascript uses the object reference in the Hashtables. It also makes sense as you could get collisions otherwise. Additionally, if you change an object that is included in a hashtable so that it equals to another one, what should happen then?


Now in a lot of cases, you probably know how the object is built and how you can get its identity. Imagine a player that has a unique username, e.g.:

 function Player(username, password) {
   this.username = username;
   this.password = password
 }

Now when we want to build a Set to check if an username is already existing, it makes sense to just use the Players username instead of the player itself:

 const a = new Player("a", "super secret");
 const b = new Player("b", "****");
 new Set([a.username, b.username]);

Or you could define a way to build up a unique key from the players properties:

 Player.prototype.identity = function() {
   return this.username + "°" + this.password;
 };

So one can do:

 const a = new Player("this is", "equal");
 const b = new Player("this is", "equal");
 console.log(
   a === b, // false
   a.identity() === b.identity() // true
 );

 const players = new Set([a.identity()]);
 players.has(b.identity()); // true
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151