自定义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运算符的逻辑,实现更灵活的类型检查机制。这在创建验证器、特殊数据类型的类或者需要复杂实例检查的场景中非常有用。

为什么这样设计

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

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

相关推荐
天下代码客1 小时前
使用electronc框架调用dll动态链接库流程和避坑
前端·javascript·vue.js·electron·node.js
weixin199701080161 小时前
【性能提升300%】仿1688首页的Webpack优化全记录
前端·webpack·node.js
冰暮流星1 小时前
javascript之数组
java·前端·javascript
晚霞的不甘2 小时前
Flutter for OpenHarmony天气卡片应用:用枚举与动画打造沉浸式多城市天气浏览体验
前端·flutter·云原生·前端框架
xkxnq2 小时前
第五阶段:Vue3核心深度深挖(第74天)(Vue3计算属性进阶)
前端·javascript·vue.js
三小河2 小时前
Agent Skill与Rules的区别——以Cursor为例
前端·javascript·后端
Hilaku2 小时前
不要在简历上写精通 Vue3?来自面试官的真实劝退
前端·javascript·vue.js
三小河2 小时前
前端视角详解 Agent Skill
前端·javascript·后端
Aniugel3 小时前
单点登录(SSO)系统
前端
鹏多多3 小时前
移动端H5项目,还需要react-fastclick解决300ms点击延迟吗?
前端·javascript·react.js