I'm writing some custom classes in JavaScript and I would like their toString
method to return a value that reflects the class itself rather than the Object class. For example:
function MyClass(){}
var my_object=new MyClass();
alert(my_object);// Returns "[object Object]"
If I instantiate an HTMLImageElement the result is different:
var my_image=new Image();
alert(my_image);// Returns "[object HTMLImageElement]"
I can override the toString method for my custom class like this:
MyClass.prototype={
toString:function(){
return "[object MyClass]";
}
};
Overriding the toString
method allows me to get a result that reflects my class name, but I feel like this approach is not the same one used by the HTMLImageElement. Is it? Is there a way to change the result of toString
without overriding it in the prototype? Are built in classes like HTMLImageElement actually JavaScript objects or are they something else?
When you use...
function MyClass(){}
var my_object = new MyClass();
... my_object.toString
is inherited from Object.prototype
:
my_object.hasOwnProperty('toString'); // false
MyClass.prototype.hasOwnProperty('toString'); // false
Object.prototype.hasOwnProperty('toString'); // true
/* => */ my_object.toString === Object.prototype.toString; // true
In the case of Image
instances, they inherit toString
from Object.prototype
too:
var my_image = new Image();
my_image.hasOwnProperty('toString'); // false
HTMLImageElement.prototype.hasOwnProperty('toString'); // false
HTMLElement.prototype.hasOwnProperty('toString'); // false
Node.prototype.hasOwnProperty('toString'); // false
EventTarget.prototype.hasOwnProperty('toString'); // false
Object.prototype.hasOwnProperty('toString'); // true
/* => */ my_image.toString === Object.prototype.toString; // true
Object.prototype.toString
is defined as
15.2.4.2 Object.prototype.toString ( )
When the
toString
method is called, the following steps are taken:
- If the
this
value isundefined
, return"[object Undefined]"
.- If the
this
value isnull
, return"[object Null]"
.- Let
O
be the result of callingToObject
passing thethis
value as the argument.- Let
class
be the value of the [[Class]] internal property ofO
.- Return the String value that is the result of concatenating the three Strings
"[object "
,class
, and"]"
.
The difference is that the internal [[Class]] of my_object
is "Object"
, but the internal [[Class]] of my_image
is "HTMLImageElement"
.
Therefore,
HTMLImageElement
do not produce a custom string by overriding Object.prototype.toString
, they use a custom [[Class]] instead.But you can't use the same approach, at least in ECMAScript 5:
8.6.2 Object Internal Properties and Methods
This specification defines no ECMAScript language operators or built-in functions that permit a program to modify an object’s [[Class]] or [[Prototype]] internal properties