内部 [[Class]]

typeof 的结果为 "object" 的值(比如数组)被额外地打上了一个内部的标签属性 [[Class]](请把它考虑为一个内部的分类方法,而非与传统的面向对象编码的类有关)。这个属性不能直接地被访问,但通常可以间接地通过在这个值上借用默认的 Object.prototype.toString(..) 方法调用来展示。举例来说:

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

所以,对于这个例子中的数组来说,内部的 [[Class]] 值是 "Array",而对于正则表达式,它是 "RegExp"。在大多数情况下,这个内部的 [[Class]] 值对应于关联这个值的内建的原生类型构造器(见下面的讨论),但事实却不总是这样。

基本类型呢?首先,nullundefined

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

你会注意到,不存在 Null()Undefined() 原生类型构造器,但不管怎样 "Null""Undefined" 是被暴露出来的内部 [[Class]] 值。

但是对于像 stringnumber、和 boolean 这样的简单基本类型,实际上会启动另一种行为,通常称为“封箱(boxing)”(见下一节“封箱包装器”):

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

在这个代码段中,每一个简单基本类型都自动地被它们分别对应的对象包装器封箱,这就是为什么 "String""Number"、和 "Boolean" 分别被显示为内部 [[Class]] 值。

注意: 从 ES5 发展到 ES6 的过程中,这里展示的 toString()[[Class]] 的行为发生了一点儿改变,但我们会在本系列的 ES6 与未来 一书中讲解它们的细节。