Lodin
Lodin

Reputation: 2068

How to disable Symbol.hasInstance for inheritors in JavaScript?

I created a proxy class B that redirects instantiation checks to the class A via Symbol.hasInstance. So, if I run the instanceof check against the B class, any inheritor of the A class will pass.

However, I want to inherit the B class, and I don't want the inheritors to follow the B class logic. I would like them to have their original identity and run the default instanceof logic for them. In the code below it is a C class.

However, by default, the Symbol.hasInstance property is inherited. How can I disable it for children classes?

class A {}

class B {
  static [Symbol.hasInstance](instance) {
    return instance instanceof A;
  }
}

class C extends B {}

class D extends A {}

const d = new D();

console.log(d instanceof B); // should be true
console.log(d instanceof C); // should be false

I already tried the following code:

Object.defineProperty(C, Symbol.hasInstance, {value: null});

It works for Chrome and Firefox but does not work for Edge throwing the following error:

The value of the property 'Symbol[Symbol.hasInstance]' is not a Function object

Is there any other way to remove/disable the Symbol.hasInstance that works in Edge as well?

Upvotes: 1

Views: 184

Answers (1)

Bergi
Bergi

Reputation: 665276

It's a method, and you can check which class it was called on using the this context. So fall back to the default implementation for everything that is not B, and therefore likely was a subclass of it that inherited the method:

class B {
  static [Symbol.hasInstance](instance) {
    if (this === B)
      return A.prototype.isPrototypeOf(instance);
    else
      return this.prototype.isPrototypeOf(instance);
  }
}

(Notice you cannot use instanceof this here, as that would lead to infinite recursion)

Upvotes: 3

Related Questions