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

为什么这样设计

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

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

相关推荐
2501_94452554几秒前
Flutter for OpenHarmony 个人理财管理App实战 - 支出分析页面
android·开发语言·前端·javascript·flutter
李白你好41 分钟前
Burp Suite插件用于自动检测Web应用程序中的未授权访问漏洞
前端
刘一说2 小时前
Vue 组件不必要的重新渲染问题解析:为什么子组件总在“无故”刷新?
前端·javascript·vue.js
徐同保3 小时前
React useRef 完全指南:在异步回调中访问最新的 props/state引言
前端·javascript·react.js
刘一说3 小时前
Vue 导航守卫未生效问题解析:为什么路由守卫不执行或逻辑失效?
前端·javascript·vue.js
一周七喜h4 小时前
在Vue3和TypeScripts中使用pinia
前端·javascript·vue.js
weixin_395448914 小时前
main.c_cursor_0202
前端·网络·算法
东东5164 小时前
基于vue的电商购物网站vue +ssm
java·前端·javascript·vue.js·毕业设计·毕设
MediaTea4 小时前
<span class=“js_title_inner“>Python:实例对象</span>
开发语言·前端·javascript·python·ecmascript
梦梦代码精5 小时前
开源、免费、可商用:BuildingAI一站式体验报告
开发语言·前端·数据结构·人工智能·后端·开源·知识图谱