Search code examples
javascriptarraysprototypeconsole.loges6-class

Change console logging name of object extended from built-in Array


I have a basic class extending Array like the following:

class Vector extends Array {
  constructor(array) {
    // doesn't handle special case of length 1 array
    super(...array);
  }
  // more code
}

Even if I try to change the name and toString prototypes, I still get it printed as Array:

Vector.constructor.prototype.toString = () => "Vector";
new Vector([1,2,3]) // shows Array(3) [ 1, 2, 3 ] in Firefox console

How can I get the class to show up as Vector(3) [ 1, 2, 3 ] in console?


Solution

  • I think Edge/Chrome/node who use V8 engine try to be smart and show object as Vector in console. You don't need the line Vector.constructor.prototype.toString = () => "Vector"; for that to happen, they will show it anyway as Vector

    Firefox on the other hand seems to show only JS built-in types in the console output. For simple class it will show Object. But chrome will show class name.

    Secondly, your understanding on JS Object model is incorrect. Vector.constructor is not your constructor function on your line 2. But it is a constructor from which Vector class is made. Remember ultimately, class is a function and function in JS is first class objects.

    Since Vector is a function it is created from Function object. Hence:

    Vector.constructor === Function
    // true
    

    Function is constructor for all functions in JS. So what you are effectively doing is changing all functions:

    Vector.constructor.prototype.toString = () => "Vector";
    // effectively means
    // Function.prototype.toString = () => "Vector";
    
    // we can test it
    function anyFunction() {}
    anyFunction.toString()
    // "Vector"
    

    Your constructor on your line 2 is really represented by Vector itself.

    Vector.prototype.toString = () => "Vector";
    (new Vector([1,2])).toString();
    // "Vector"
    

    Same thing can be represented by overriding in class syntax:

    class Vector extends Array {
      // .. your code...
      toString() {
            return "Vector [" + super.toString() + "]";
      }
    }
    
    (new Vector([1,2])).toString()
    // "Vector [1,2]"
    

    Unfortunately, though it will not meet your original expectations.

    To invoke toString from console.log you can have some concatenation:

    let v = new Vector([1,2])
    console.log("Variable is " + v)
    // "Variable is Vector [1,2]"