Okay, think of it like this:
- All values in JavaScript are actually instances of a class. Even
undefined
and null
are implemented as singleton objects in the interpreter. For example undefined
is actually Undefined.instance
in Rhino (implemented in Java).
- The
toString
method defined exposes the class name of the JavaScript value. However since the value is not the class itself but an instance of the class, toString
returns the a string of the form [object ClassName]
.
- Yes, the
[object *]
form is redundant. However someone wanted it to be like that and so we're stuck with it. Now that it's there it will cause a lot of problems if it's suddenly changed. Old code that depends upon it may break.
Edit: It's important to note when JavaScript ends and the interpreter begins. For example when you call a function in JavaScript the interpreter creates a new execution context, which is an object in the language in which the JavaScript interpreter is written (not JavaScript itself).
Similarly, the [[Class]]
of a JavaScript value is the class in the language in which the JavaScript interpreter is written, which is used to create instances of that class. For example, in Rhino functions are instances of the class org.mozilla.javascript.BaseFunction
. This class has a method called getClassName
which returns Function
(the [[Class]]
of the instances of BaseFunction
).
Similarly there's a class called org.mozilla.javascript.Undefined
which has a static property called instance
which is the singleton instance of Undefined
.