自定义instanceof运算符行为API: Symbol.hasInstance

今天翻zod的源码,发现有个之前没见过的,应该也没听说的API:Symbol.hasInstance

ts 复制代码
export /*@__NO_SIDE_EFFECTS__*/ function $constructor<T extends ZodTrait, D = T["_zod"]["def"]>(
  name: string,
  initializer: (inst: T, def: D) => void,
  params?: { Parent?: typeof Class }
): $constructor<T, D> {
  // ...
  // 
  Object.defineProperty(_, Symbol.hasInstance, {
    value: (inst: any) => {
      if (params?.Parent && inst instanceof params.Parent) return true;
      return inst?._zod?.traits?.has(name);
    },
  });
}

发现有个写了几年代码都没发现的API,就拿去问ai了。


Symbol.hasInstance是 JavaScript 的一个内置 Symbol,用于自定义 instanceof运算符的行为。

基本用法

默认情况下,instanceof检查对象的原型链:

js 复制代码
class Animal {}
class Dog extends Animal {}

const dog = new Dog();
console.log(dog instanceof Dog);     // true
console.log(dog instanceof Animal);   // true
console.log(dog instanceof Object);   // true

使用 Symbol.hasInstance 自定义行为

你可以通过定义静态的 Symbol.hasInstance方法来改变 instanceof的行为:

js 复制代码
class MyClass {
    static [Symbol.hasInstance](instance) {
        // 自定义判断逻辑
        return typeof instance === 'object' && 
               instance !== null && 
               instance.value === 42;
    }
}

const obj1 = { value: 42 };
const obj2 = { value: 100 };
const obj3 = null;

console.log(obj1 instanceof MyClass); // true
console.log(obj2 instanceof MyClass); // false
console.log(obj3 instanceof MyClass); // false

实际应用场景

1. 基于属性的实例检查

js 复制代码
class Validator {
    static [Symbol.hasInstance](obj) {
        return typeof obj === 'object' && 
               obj !== null && 
               typeof obj.validate === 'function';
    }
}

const validObj = {
    validate() { return true; }
};

const invalidObj = { name: "test" };

console.log(validObj instanceof Validator);   // true
console.log(invalidObj instanceof Validator);  // false

2. 数字范围检查

js 复制代码
class PrimeNumber {
    static isPrime(num) {
        if (num <= 1) return false;
        for (let i = 2; i <= Math.sqrt(num); i++) {
            if (num % i === 0) return false;
        }
        return true;
    }
    
    static [Symbol.hasInstance](num) {
        return Number.isInteger(num) && this.isPrime(num);
    }
}

console.log(2 instanceof PrimeNumber);    // true
console.log(7 instanceof PrimeNumber);    // true
console.log(4 instanceof PrimeNumber);    // false
console.log(9 instanceof PrimeNumber);    // false

3. 数组内容检查

js 复制代码
class NumericArray {
    static [Symbol.hasInstance](arr) {
        return Array.isArray(arr) && 
               arr.every(item => typeof item === 'number');
    }
}

console.log([1, 2, 3] instanceof NumericArray);     // true
console.log([1, '2', 3] instanceof NumericArray);   // false

注意事项

  1. 1.必须是静态方法 :Symbol.hasInstance必须定义为类的静态方法
  2. 2.影响所有 instanceof 检查:会改变该类的所有实例检查行为
  3. 3.谨慎使用:过度使用可能使代码难以理解
js 复制代码
class CustomClass {
    // 正确:静态方法
    static [Symbol.hasInstance](instance) {
        return true; // 所有对象都是实例
    }
    
    // 错误:实例方法(不会生效)
    [Symbol.hasInstance](instance) {
        return false;
    }
}

console.log({} instanceof CustomClass); // true(总是返回 true)

总结

Symbol.hasInstance的主要用途是让开发者能够自定义 instanceof运算符的逻辑,实现更灵活的类型检查机制。这在创建验证器、特殊数据类型的类或者需要复杂实例检查的场景中非常有用。

为什么这样设计

  • 灵活性:允许对象通过特征标记而非严格的类继承来表示类型
  • 组合优于继承:支持特征组合,一个对象可以有多个特征
  • 运行时类型检查:可以在运行时动态添加/移除类型特征

这种模式在需要灵活类型系统的库中很常见,特别是那些需要支持动态类型或混合类型的场景。

相关推荐
sm_926787053 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
IMPYLH3 小时前
HTML 的 <video> 元素
前端·html
溪语流沙3 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
逐光者9334 小时前
STM32——SPI 屏 · Flash · 高速
java·前端·stm32
To_OC4 小时前
同样是让 AI 写全栈,为什么别人一句话就够了
前端·前端框架·next.js
CDwenhuohuo4 小时前
electron pc项目打包成桌面端
前端·javascript·electron
前端大斗师4 小时前
「大于 1000」把 1000 元那单也算进去了:我在 Vue3 订单页对了 10 句话
前端·人工智能·typescript·大模型·原力计划
Jmyd01235 小时前
用 Web VR 引擎搭建 3D 虚拟展厅:从素材上云到多端实时渲染的完整数据链路
前端·3d·vr·三维数字化
刘天远5 小时前
Agent成本核算实现:事件表、状态分布与Python归集
前端·数据库·人工智能·python
欣欣之王来了5 小时前
开发环境准备:Node.js、npm、VS Code安装配置
前端·学习·架构·项目·vue3教程