object.getprototypeof 配合私有 symbol 可实现轻量、可靠且不可伪造的类归属校验:为每个类声明唯一 symbol 挂载于 prototype,通过遍历原型链检测该 symbol 是否存在,支持继承、抗篡改且跨上下文安全。

在大型项目中,用 Object.getPrototypeOf 配合 Symbol 可以实现轻量、可靠且不可伪造的类归属校验,避免依赖构造函数名(易被篡改)或 instanceof(受原型链污染/跨上下文限制)。
用 Symbol 作为类的唯一身份标识
每个类定义时声明一个私有 Symbol,挂载在类本身或原型上,作为该类的“指纹”。这个 Symbol 不会被枚举,也无法被外部复现:
- 不使用
Symbol.for,防止全局冲突;必须用Symbol()创建唯一值 - 推荐挂载到类的
prototype上,便于实例通过原型链访问 - 例如:class User { } → User.prototype[User.$$type] = User.$$type;
通过 getPrototypeOf 向上追溯并匹配 Symbol
校验时,不直接读取实例的 constructor,而是用 Object.getPrototypeOf(obj) 逐级获取原型,检查其是否拥有目标类的 Symbol 属性:
- 每次拿到原型后,用
Reflect.has(proto, symbol)或proto[symbol] === symbol判断归属 - 支持多层继承:只要某一级原型上有该 Symbol,就视为属于该类或其子类
- 比
instanceof更健壮——即使构造函数被重写或原型被替换,只要 Symbol 还在对应原型上,校验仍有效
封装可复用的校验工具函数
为避免重复逻辑,可封装一个通用函数,接收实例和目标类,返回是否归属:
- 函数内部先从目标类读取预设的 Symbol(如
cls.$$type) - 然后从实例开始,循环调用
Object.getPrototypeOf,直到原型为null - 任一原型上存在该 Symbol,立即返回
true;遍历完无匹配则返回false - 示例调用:isInstanceOf(user, User),语义清晰且不依赖全局环境
配合 TypeScript 做编译期辅助(可选增强)
虽然 Symbol 校验是运行时行为,但可在类型层面加强约束:
- 为每个类声明一个私有静态 Symbol 字段,如 static readonly $$type = Symbol();
- 在类型定义中将
$$type加入 public interface(仅用于类型提示,不参与运行时) - 这样 IDE 能识别校验函数参数类型,TS 编译器也能捕获传入非目标类的错误










