内部属性 [[Class]]

376 阅读1分钟

所有 typeof 返回值为 "object" 的对象(如数组)都包含一个内部属性 [[Class]](我们可以把它看作一个内部的分类,而非 传统的面向对象意义上的类)。这个属性无法直接访问,一般通过 Object.prototype.toString(..) 来查看。例如:

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

数组的内部[[class]]属性值是"Array",正则表达式是"RegExp",多数情况下,对象的内部[[class]]属性和创建该对象的内建原生构造函数相对应,但并非总是如此.

  • 基本数值类型
Object.prototype.toString.call(null); // "[object Null]"
Object.prototype.toString.call(undifined); // "[object Undefined]"

虽然Null()和Undefined()这样的原生构造函数并不存在,但是内部[[class]]属性值仍然是"Null"和"Undefined".

  • 其他基本类型值
Object.prototype.toString.call('pat');   // "[object String]"
Object.prototype.toString.call(123);       // "[object Number]"
Object.prototype.toString.call(true);       // "[object Boolean]"

基本类型值被各自的封装对象自动包装,所以他们的内部[[class]]属性值分别为"String","Number"和"Boolean"

  • 但自己创建的类和普通对象不会有这份特殊待遇,toString() 找不到 toStringTag 属性时只好返回默认的 Object 标签:
class myClass {} 
Object.prototype.toString.call(new myClass()); // "[object Object]" 
const obj = {}; 
Object.prototype.toString.call(obj); // "[object Object]"

加上 toStringTag 属性,自己定义的类也会有自定义的类型标签了:

class myClass {   
  get [Symbol.toStringTag]() {     
    return "myClass1";   
  } 
} 
Object.prototype.toString.call(new myClass()); // "[object myClass1]" 

const obj = {}; 
Object.defineProperty(obj,
                      Symbol.toStringTag, 
                      { value: 'CustomObject' }); // "[object CustomObject]"