跳到主要内容

类型标签与扩展内建

Object.prototype.toString 如何当增强版 typeof 用?​

  • 机制: 原生 toString 只看 this, 可取出后在任意值上执行, 结果形如 [object Tag];
  • 用法: Object.prototype.toString.call(value), 常写作 {}.toString.call(value);
值{}.toString.call(值)
123 / null[object Number] / [object Null]
[] / 函数[object Array] / [object Function]
  • 自定义标签: 对象的 Symbol.toStringTag 决定 Tag, 如 { [Symbol.toStringTag]: "User" } → [object User];
  • 取舍: 要类型字符串用 {}.toString, 要按继承层次判断用 instanceof;

扩展内建类会有什么连锁效果?​

  • 可行: class PowerArray extends Array {} 后实例既有数组能力, 也有自定义方法;
  • 连锁: filter/map 内部用 this.constructor 造新对象, 所以返回的仍是 PowerArray, 自定义方法可继续用;
  • 拦截: 静态 getter Symbol.species 指定内建方法实际使用的构造函数, 返回 Array 即停止「传递」扩展方法;
class PowerArray extends Array {
isEmpty() {
return this.length === 0;
}
static get [Symbol.species]() {
return Array;
}
}
new PowerArray(1, 20).filter((x) => x > 10).isEmpty(); // TypeError: 结果是 Array
  • 同类: Map、Set 也遵循 Symbol.species, 见 Array 方法;

内建类为什么不继承彼此的静态成员?​

  • 常规: class B extends A 时静态成员也会继承, 见 静态成员;
  • 例外: Date.prototype 继承 Object.prototype, 但 Date.[[Prototype]] 不指向 Object, 而是 Function.prototype;
  • 结果: Date.keys、Array.keys 这类「继承来的」静态方法并不存在;