Equality methods and hashcodes

There are several different ways in which two objects can be equal to each other, and jsclass provides equality methods with different semantics. It’s important to know the difference as there are parts of the framework that expect certain equality methods to be used to make integration as painless as possible.

If you want to use an object as a key in a Hash, you’ll need to override its equals() and hash() methods in a consistent way; see below for more information.

Built-in operators: == and ===

JavaScript has two built-in equality operators, == for equality and === for identity. The expression foo === bar returns true iff foo and bar refer to the same object. For primitive values (numbers, strings, boolean values) this implies that both must have the same value and the same type. So '5' === '5' is true, but '5' === 5 is false. Similarly false === null and false === 0 are false.

The equality operator == is more lenient. For objects it has the same effect as ===, but for primitives it performs type casting to figure out whether two values are “equivalent”. So, '5'==5 is true, as are false==null and false==0.

Sort position equality: object.eq(other)

This method is provided by the Comparable module and returns true iff object and other have the same sort priority. Two objects may appear equal in terms of eq() but may not be completely meaningfully equal. It simply means object is neither “less than” nor “greater than” other, and they may appear in either order in a sorted collection. Though not used directly, the related method compareTo() is used by Hash and SortedSet for sorting objects.

Equivalence: object.equals(other)

This returns true iff object and other are meaningfully equal. The default implementation of this method in Kernel just uses === to compare the objects; classes may override this method to provide more meaningful comparison. For example, Set#equals() returns true iff used to compare two sets that contain the same members. The following classes expect objects to implement equals():

jsclass does not modify built-in JavaScript classes, but the above classes do contain methods for comparing Array and Object instances. Two arrays are considered equal if their elements are all equal, and two objects with no equals() method are considered equal if they have the same set of keys-value pairs, much like Hash equality.

If you implement equals() in one of your own classes, it should obey these rules:

You must also override hash() such that if x.equals(y) is true, then x.hash() === y.hash() is also true. Otherwise, your objects will not work as a key in a Hash or as a member of a Set.

Hash equality: object.hash()

The hash() method is used internally by Hash to improve key search performance by splitting the stored pairs into “buckets” and assigning each bucket a hashcode. (See Wikipedia for more on how hashtables work.) When you ask a Hash for the value for a given key, it converts the key to a hashcode to figure out which bucket to look in.

The default implementation of hash() in Kernel produces a different value for every object. If you implement equals() in your class such that two objects can be considered equal, you will need to make sure that two equal objects return the same hashcode; two equal objects should return the same value when given as keys to a Hash, but if they have different hashcodes, the hash will look in different places to find their values.

So, if you implement equals() in a class, you must also implement hash() such that: