Why EventTarget subclass instances lose their names?

Tags: ,



The current version of JavaScript implements EventTarget as a class instead of an interface, so you can create an instance of EventTarget with all the expected methods.

I tried to copy/paste the EventTarget example in the console (on both Chrome and Firefox) but when I inspect the myEventTarget object (that is build as a subclass of EventTarget named MyEventTarget), the console says that myEventTarget is an EventTarget, not a MyEventTarget.

This is the code

//this is the MDN example
class MyEventTarget extends EventTarget {
  constructor(mySecret) {
    super();
    this._secret = mySecret;
  }

  get secret() { return this._secret; }
};

let myEventTarget = new MyEventTarget(5);
let value = myEventTarget.secret;  // == 5
myEventTarget.addEventListener("foo", function(e) {
  this._secret = e.detail;
});

let event = new CustomEvent("foo", { detail: 7 });
myEventTarget.dispatchEvent(event);
let newValue = myEventTarget.secret; // == 7

// the following is the code I have added
// everything seems to work as usual, ie
console.log(myEventTarget instanceof MyEventTarget)
// the console says that is true

// but if I try to print the instance...
console.log(myEventTarget)
// EventTarget { _secret: 7 }

Why the console says that myEventTarget is just an EventTarget?

I found this thing quite uncommon because if I type the following code the console says that myEventTarget is actually a MyEventTarget instance

class MyEventTarget extends class SomeOtherClass{} {
  constructor(mySecret) {
    super();
    this._secret = mySecret;
  }

  get secret() { return this._secret; }
};

let myEventTarget = new MyEventTarget(5);

console.log(myEventTarget instanceof MyEventTarget)
// the console diligently says that is true

// and if I try to print the instance...
console.log(myEventTarget)
// ...the console correcly says
// MyEventTarget { _secret: 5 }

so if I use EventTarget as superclass, the instances lose their constructor name? I understand that is not a big deal, I think that print class names is just for debugging purpose but there is a reason for this?

Answer

This happens because EventTarget overrides Symbol.toStringTag and you inherit this behaviour. You can override it to be whatever you want.

class MyEventTarget extends EventTarget {
  constructor(mySecret) {
    super();
    this._secret = mySecret;
  }

  get secret() { return this._secret; }
  
  get [Symbol.toStringTag]() {
    return this.constructor.name
  }
};

let myEventTarget = new MyEventTarget(5);
let value = myEventTarget.secret;  // == 5
myEventTarget.addEventListener("foo", function(e) {
  this._secret = e.detail;
});

let event = new CustomEvent("foo", { detail: 7 });
myEventTarget.dispatchEvent(event);
let newValue = myEventTarget.secret; // == 7

// the following is the code I have added
// everything seems to work as usual, ie
console.log(myEventTarget instanceof MyEventTarget)
// the console says that is true

// but if I try to print the instance...
console.log(myEventTarget)
// MyEventTarget { _secret: 7 }

console.log(Object.prototype.toString.call(myEventTarget))
// [object MyEventTarget]


Source: stackoverflow