类型标签与扩展内建
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这类「继承来的」静态方法并不存在;