- 开发工具
【免费下载链接】collect.js
💎 Convenient and dependency free wrapper for working with arrays and objects
本文以 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);六、边界情况与注意事项
- 原始类型总是被过滤掉:
instanceof对字符串、数字、布尔值、null、undefined均返回false,因此whereInstanceOf(Player)不会保留这些元素,即使你传入的是包装类型之外的原始值。 - 子类会被包含:如前文所述,
Dog instanceof Animal为true,筛选父类会连带筛出子类实例。这是instanceof的固有语义,不是缺陷。 - 跨 realm(执行环境)对象判断失效:
instanceof依赖原型链,来自不同 realm(如不同 iframe / VM 上下文)的对象即使结构相同,也可能无法被识别为同一类实例。此类场景需谨慎使用。 - 参数必须是函数:
type应为 class 或构造函数。传入非函数值(如字符串'Player')会导致item instanceof type抛TypeError。 - 不可变操作:过滤结果返回新集合,原集合不变,可放心链式调用:
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
相关推荐
collect.js `whereNotIn()` 详解:按键值排除集合项的不包含过滤指南
collect.js whereNotIn 详解:按键值排除集合项的不包含过滤指南 whereNotIn 是 collect.js 中用于 反向包含过滤 的核心
开发工具collect.js `split()` 方法完全指南:将集合按组数切分的高效实践
collect.js split 方法完全指南:将集合按组数切分的高效实践 split 是 collect.js 中一个专用于"按组数切分集合"的方法:与按固定
开发工具collect.js 的 count() 方法:统计集合元素数量的完整指南
collect.js 的 count 方法:统计集合元素数量的完整指南 导读 count 是 collect.js 中用于统计集合元素总数的基础方法,它同时兼容
开发工具
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考