Symbol.equal - a way to define the weak equals operator on objects

I propose something new for object comparison called Symbol.equal.

The == operator should call the Symbol.equal method if the left hand side is an object or only the right hand side is an object.

example:

class Box{
    #value=0;
    constructor(value){
        this.#value=value;
    }
    get value(){
        return this.#value;
    }
    [Symbol.equals](other){
        return other instanceof Box && other.value == this.value;
    }
}
assert(new Box(0) == new Box(0))

Some previous related discussions:

1 Like

Why? What's the problem you're trying to solve?

Other libraries might have different equality method names which makes it inconsistent and you might end up trying to call undefined or being too strict

btw: the other proposals solve this issue too and I don't care if you do mine or not

Considering that == is aggressively discouraged in every form except perhaps == null, why would it be a good idea to begin encouraging its use?

What would be the benefit of a consistent way of comparing arbitrary objects? Two different kinds of objects are only comparable if they know about each other, in which case they'd need to both participate in the API, which they could do just by agreeing on a method name.

code verbosity for general purpose library usage

x == y invisibly calling a protocol seems extremely less readable than x.equals(y) or the equivalent, to me.

well, at least its less verbose

valueOf enters the conversation:

({ valueOf: () => 123 }) == 123

I think anything more elegant than that would be great and because indeed == is rare out there and old code won't be affected, I believe this idea is not that bad, just the name (maybe?) as I'd go for Symbol.eqeq instead or Symbol.equality as described on MDN Equality (==) - JavaScript | MDN

edit I also agree x.equals(y) doesn't need to check for Symbol.equality in obj to branch == from === but still, == via symbol would be cool but I also think for null or undefined comparison that protocol should not be called or it will break working code with good intents.

1 Like

On a second though, wouldn't Object.equal(a, b) help solving the operator hidden gotcha and help comparing via:

  • returns true if Object.is(a, b)
  • returns true if a == b
  • returns true if both objects have a Symbol.equal attached or inherited and a[Symbol.equal](b) and b[Symbol.equal](a)) are both true
  • returns false otherwise

... or maybe not?