☰
collect.js 的 `whereInstanceOf()` 方法:按类类型过滤集合的完整指南
2026/10/15 2:10:53 网站建设 项目流程
  • 开发工具

【免费下载链接】collect.js

💎 Convenient and dependency free wrapper for working with arrays and objects

项目地址:https://gitcode.com/gh_mirrors/co/collect.js
点击查看免费下载

本文以 collect.js 仓库中 docs/api/whereInstanceOf.md 文档为核心,结合 src/methods/whereInstanceOf.js 源码与其测试用例,系统讲解whereInstanceOf()的用法、实现原理、适用场景与边界情况。读完本文,你将掌握如何在 collect.js 集合中按类类型精确筛选对象,并能将它与filter()、where()、mapInto()等方法组合使用。

一、方法概述

whereInstanceOf()是 collect.js 提供的一个过滤方法,它接收一个类(class)或构造函数作为参数,返回一个新集合,其中只保留该类型实例的元素。它与 Laravel Collections 中同名方法 API 一致,适合在集合中混合存放多种类型对象时,快速抽取出某一特定类型的成员。

const collection = collect([ new Player('Firmino'), new Player('Salah'), new Manager('Klopp'), ]); const filtered = collection.whereInstanceOf(Player); filtered.all(); // [ // new Player('Firmino'), // new Player('Salah'), // ]

上面的示例中,集合同时包含Player与Manager两种对象,调用whereInstanceOf(Player)后,返回的集合只保留了Player实例。

二、基本用法与参数说明

whereInstanceOf(type)接受一个参数:

参数类型必填说明
type构造函数(class / function)是用于instanceof判断的类或构造函数

调用后返回一个新的Collection实例,原集合不会被修改(下文源码部分会展开说明)。

与filter(callback)不同,whereInstanceOf()不需要你手写判断逻辑,只要把类型传进去即可,语义更明确,可读性更强。

三、源码实现剖析

whereInstanceOf()的完整实现非常简洁,只有一行核心逻辑,见 src/methods/whereInstanceOf.js:

'use strict'; module.exports = function whereInstanceOf(type) { return this.filter(item => item instanceof type); };

3.1 底层调用链:复用filter()

从源码可以看到,whereInstanceOf()本质上是filter()方法的一个包装:它为集合中每一个元素执行item instanceof type的真值测试,并把该回调委托给filter()处理。

filter()的实现位于 src/methods/filter.js。它根据集合底层数据结构(数组或对象)分别走filterArray或filterObject分支:

module.exports = function filter(fn) { const func = fn || false; let filteredItems = null; if (Array.isArray(this.items)) { filteredItems = filterArray(func, this.items); } else { filteredItems = filterObject(func, this.items); } return new this.constructor(filteredItems); };

注意最后一行new this.constructor(filteredItems):filter()始终构造并返回一个新的 Collection 实例。因此whereInstanceOf()也是不可变的(immutable)——过滤结果不会改动原集合。

3.2 方法注册与挂载

whereInstanceOf被注册到Collection原型上,见 src/index.js:

Collection.prototype.whereInstanceOf = require('./methods/whereInstanceOf');

src/index.js定义了Collection构造器与collect()工厂函数,所有方法均以require方式挂载到原型上。这也意味着:只要collect()创建出的集合,都天然具备whereInstanceOf()能力。

3.3 测试验证

仓库在 test/methods/whereInstanceOf_test.js 中为该方法提供了测试用例,使用构造函数Player与Manager构造对象并断言过滤结果:

const filtered = collection.whereInstanceOf(Player); expect(filtered.all()).to.eql([Firmino, Salah]); expect(collection.all()).to.eql([Firmino, Salah, Klopp]);

第二行断言明确验证了原集合保持不变,与上文源码分析的不可变语义相互印证。测试通过 test/tests.js 统一加载运行(mocha test/tests.js),该文件还会自动检查每个src/methods下的方法都有对应文档与测试,确保 API 全覆盖。

四、适用场景实战

4.1 从混合类型集合中抽取单一类型

业务中经常出现“事件队列”“日志列表”“UI 组件列表”等混合类型场景,例如:

class Animal {} class Dog extends Animal {} class Cat extends Animal {} const collection = collect([ new Dog('Rex'), new Cat('Tom'), new Dog('Buddy'), new Animal('generic'), ]); const dogs = collection.whereInstanceOf(Dog); dogs.all(); // [Dog, Dog](Dog 实例) const animals = collection.whereInstanceOf(Animal); animals.all(); // [Dog, Dog, Cat, Animal](所有 Animal 及其子类实例)

这里体现了instanceof的继承语义:Dog与Cat都满足instanceof Animal,因为它们是Animal的子类。如果你只想筛出“恰好是该类型”的元素,则需要结合其他手段(例如比较constructor),whereInstanceOf()本身是包含子类的。

4.2 与mapInto()配合的“实例化-筛选”管线

mapInto()方法(见 docs/api/mapInto.md 与 src/methods/mapInto.js)可以把原始数据批量实例化为指定类的对象:

const Player = function (name) { this.name = name; }; const collection = collect(['Firmino', 'Salah', 'Núñez']); const players = collection.mapInto(Player); // players.all() => [Player, Player, Player]

当后续数据流中混入其他类型时,whereInstanceOf(Player)就可以用来做类型收窄,保证下游只处理Player实例:

const mixed = collect([...players.all(), 'not-a-player', 42, new Manager('Klopp')]); const clean = mixed.whereInstanceOf(Player); clean.all(); // [Player, Player, Player]

4.3 对对象(字典)集合的过滤

由于filter()同时支持数组与对象两种底层结构,whereInstanceOf()对对象形态的集合同样适用:

const collection = collect({ attacker: new Player('Salah'), coach: new Manager('Klopp'), backup: new Player('Díaz'), }); const players = collection.whereInstanceOf(Player); players.all(); // { // attacker: Player, // backup: Player, // }

五、与其他过滤方法的对比

collect.js 提供了一系列where*过滤方法,各有侧重,选择时可按需使用:

方法过滤依据典型用法
whereInstanceOf(type)元素是否为某类的实例whereInstanceOf(Player)
where(key, value)键 / 值对(支持比较运算符与点号嵌套键)where('price', '>', 100)
whereIn(key, array)键值是否在给定数组内whereIn('price', [100, 150])
filter(callback)任意自定义回调的真值测试filter(item => item.active)
reject(callback)与filter相反,剔除满足条件的元素reject(item => item.closed)

其中where(key, ...)系列面向普通对象属性过滤(文档见 docs/api/where.md、docs/api/whereIn.md),而whereInstanceOf()专门面向对象的运行时类型过滤。二者角度不同:前者看“属性值”,后者看“对象是谁”。当需要按属性过滤时优先where()/whereIn();当需要按类型过滤时用whereInstanceOf()语义最清晰。

另外,若想保留“不是某类型”的元素,可结合reject()(src/methods/reject.js):

const nonPlayers = collection.reject(item => item instanceof Player);

六、边界情况与注意事项

  1. 原始类型总是被过滤掉:instanceof对字符串、数字、布尔值、null、undefined均返回false,因此whereInstanceOf(Player)不会保留这些元素,即使你传入的是包装类型之外的原始值。
  2. 子类会被包含:如前文所述,Dog instanceof Animal为true,筛选父类会连带筛出子类实例。这是instanceof的固有语义,不是缺陷。
  3. 跨 realm(执行环境)对象判断失效:instanceof依赖原型链,来自不同 realm(如不同 iframe / VM 上下文)的对象即使结构相同,也可能无法被识别为同一类实例。此类场景需谨慎使用。
  4. 参数必须是函数:type应为 class 或构造函数。传入非函数值(如字符串'Player')会导致item instanceof type抛TypeError。
  5. 不可变操作:过滤结果返回新集合,原集合不变,可放心链式调用:
const result = collection .whereInstanceOf(Player) .map(player => player.name.toUpperCase());

七、小结

whereInstanceOf()是 collect.js 中语义清晰、实现轻量的类型过滤方法:

  • 用法:collection.whereInstanceOf(Type),返回新集合,原集合不变;
  • 实现:底层复用filter(),对每个元素执行item instanceof type(见 src/methods/whereInstanceOf.js);
  • 验证:测试用例见 test/methods/whereInstanceOf_test.js;
  • 定位:与where()、whereIn()的属性过滤互补,是处理混合对象集合时的首选类型筛选工具。

collect.js 整体是无依赖(dependency free)的数组/对象操作库(package.json),安装后可立即使用:

npm install collect.js --save # 或 yarn add collect.js

更多方法可查阅仓库 docs/api 目录下的独立文档,每个方法均配有独立页面、源码与测试。

  • 开发工具

【免费下载链接】collect.js

💎 Convenient and dependency free wrapper for working with arrays and objects

项目地址:https://gitcode.com/gh_mirrors/co/collect.js
点击查看免费下载
上一篇:Angular RxJS操作符精通:map、filter、switchMap等实用案例解析
下一篇:Python网络安全终极指南:HTTPS与证书验证实战教程 🛡️

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询