Internal [[Class]]

Values that are typeof "object" (such as an array) are additionally tagged with an internal [[Class]] property (think of this more as an internal classification rather than related to classes from traditional class-oriented coding). This property cannot be accessed directly, but can generally be revealed indirectly by borrowing the default Object.prototype.toString(..) method called against the value. For example:

  1. Object.prototype.toString.call( [1,2,3] ); // "[object Array]"
  2. Object.prototype.toString.call( /regex-literal/i ); // "[object RegExp]"

So, for the array in this example, the internal [[Class]] value is "Array", and for the regular expression, it’s "RegExp". In most cases, this internal [[Class]] value corresponds to the built-in native constructor (see below) that’s related to the value, but that’s not always the case.

What about primitive values? First, null and undefined:

  1. Object.prototype.toString.call( null ); // "[object Null]"
  2. Object.prototype.toString.call( undefined ); // "[object Undefined]"

You’ll note that there are no Null() or Undefined() native constructors, but nevertheless the "Null" and "Undefined" are the internal [[Class]] values exposed.

But for the other simple primitives like string, number, and boolean, another behavior actually kicks in, which is usually called “boxing” (see “Boxing Wrappers” section next):

  1. Object.prototype.toString.call( "abc" ); // "[object String]"
  2. Object.prototype.toString.call( 42 ); // "[object Number]"
  3. Object.prototype.toString.call( true ); // "[object Boolean]"

In this snippet, each of the simple primitives are automatically boxed by their respective object wrappers, which is why "String", "Number", and "Boolean" are revealed as the respective internal [[Class]] values.

Note: The behavior of toString() and [[Class]] as illustrated here has changed a bit from ES5 to ES6, but we cover those details in the ES6 & Beyond title of this series.