core-js 中 Array filtering 提案的 filterReject 实现:数组与 TypedArray 反向过滤完全指南
发布时间:2026/9/11 23:04:16来源:尧图网络
core-js 中 Array filtering 提案的 filterReject 实现数组与 TypedArray 反向过滤完全指南【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js本篇指南以仓库文档 docs/web/docs/features/proposals/array-filtering.md 为骨架系统讲解 TC39Array filtering提案在 core-js 中的落地方式Array.prototype.filterReject与%TypedArray%.prototype.filterReject的语义、模块入口、源码级实现原理与测试验证。读完你将掌握如何用filterReject完成反向过滤理解它与既有filter在内部迭代器上的实现差异并能按需选择正确的 core-js 入口点在自己的项目中安全启用该能力。提案背景为什么需要filterRejectArray filtering是 TC39 的一个早期阶段Stage 1提案其核心是引入与Array.prototype.filter语义相反的方法filterRejectfilter保留回调返回真值的元素filterReject则保留回调返回假值的元素。它可以被看作filter 逻辑取反的语法糖// 手写等价形式 [1, 2, 3, 4, 5].filter(it !(it % 2)); // [2, 4] // 提案形式 [1, 2, 3, 4, 5].filterReject(it it % 2); // [2, 4]官方文档中给出的示例与上述一致见 array-filtering.md[1, 2, 3, 4, 5].filterReject(it it % 2); // [2, 4]当过滤条件本身表述为排除语义时例如剔除偶数跳过无效项filterReject让代码意图更直接避免反复书写!取反导致的认知负担。在 core-js 中该提案目前仅实现了filterReject一个方法覆盖普通数组与全部 TypedArray 类型。仓库还保留了历史命名filterOut作为别名实现但标注了Remove fromcore-js4的清理计划见 proposals/array-filtering.js 与 modules/esnext.array.filter-out.js新代码应优先使用filterReject。Built-ins 签名与回调语义文档给出了filterReject的 TypeScript 签名见 array-filtering.mdclass Array { filterReject(callbackfn: (value: any, index: number, target: any) boolean, thisArg?: any): Arraymixed; } class %TypedArray% { filterReject(callbackfn: (value: number, index: number, target: %TypedArray%) boolean, thisArg?: any): %TypedArray%; }两个方法共用一个回调模型与filter完全一致callbackfn对每个元素执行接收三个参数——value当前元素值、index当前索引、target遍历的源对象本身回调返回值被用作布尔判定。thisArg可选回调执行时的this值。返回值一个新集合包含所有回调返回假值的元素。数组版返回普通数组TypedArray 版返回与原实例同类型的新 TypedArray。从 tests/unit-global/esnext.array.filter-reject.js 的测试断言可以确认回调契约的细节array.filterReject(function (value, key, that) { assert.same(arguments.length, 3, correct number of callback arguments); assert.same(value, 1, correct value in callback); assert.same(key, 0, correct index in callback); assert.same(that, array, correct link to array in callback); assert.same(this, context, correct callback context); }, context);即回调恰好收到 3 个参数that指向源数组this绑定到传入的thisArg未传时在非严格模式下为全局对象。返回值类型语义与filter一致filterReject的返回值类型由接收者决定普通数组遵循Symbol.species构造约定——测试中通过自定义array.constructor[Symbol.species]验证了自定义构造器会被使用array.filterReject(Boolean).foo得到1TypedArray 版返回与原实例同类型的新实例测试断言instanceof TypedArray成立且值完全一致new Uint8Array([1,2,3,4,5,6,7,8,9]).filterReject(it it % 2)得到[2, 4, 6, 8]见 tests/unit-global/esnext.typed-array.filter-reject.js。模块入口与引入方式文档列出了三条官方入口见 array-filtering.md对应 core-js 不同粒度core-js/proposals/array-filtering-stage-1 core-js(-pure)/full/array(/virtual)/filter-reject core-js/full/typed-array/filter-reject按提案整体引入需要一次性引入数组版与 TypedArray 版时使用提案聚合入口import core-js/proposals/array-filtering-stage-1;该入口的实现位于 proposals/array-filtering-stage-1.js仅两行require(../modules/esnext.array.filter-reject); require(../modules/esnext.typed-array.filter-reject);仓库还保留了兼容旧命名的 proposals/array-filtering.js它额外引入已废弃的filterOut模块同样标注TODO: Remove from core-js4。按方法按需引入更精细的做法是只引入所需方法避免打包多余 polyfill// 数组版修改 Array.prototype import core-js/full/array/filter-reject; // 仅 TypedArray 版 import core-js/full/typed-array/filter-reject; // pure 版本不污染全局原型导出为静态函数 import filterReject from core-js-pure/full/array/filter-reject;关于/virtual/入口core-js(-pure)/full/array/virtual/filter-reject是配合bind 运算符提案使用的虚拟方法入口。在core-js-pure中不能污染原生构造器的原型因此原型方法被转换为静态函数如上面的filterReject(array, cb)配合 bind 运算符::语法可以模拟原生的方法调用体验import filterReject from core-js-pure/full/array/virtual/filter-reject; const result [1, 2, 3, 4, 5]::filterReject(it it % 2); // [2, 4]虚拟入口的实现位于 full/array/virtual/filter-reject.js它通过内部getBuiltInPrototypeMethod拿到Array.prototype.filterReject并导出而 full/instance/filter-reject.js 则是供core-js-pure静态方法使用的高阶封装当参数是Array.prototype或继承自它且方法未被子类覆盖时返回虚拟方法否则返回实例自身的方法。提示core-js的/modules/路径属于内部 API不会自动注入全部依赖可能在 minor 或 patch 版本中变动见 usage.md仅推荐在自定义构建等明确场景使用常规项目请使用上面的/proposals/、/full/等入口。与 Babel 的配合filterReject属于 Stage 1 早期提案babel/preset-env的useBuiltIns只处理稳定特性不会自动注入它。若项目使用 Babel需要配合corejs选项手动引入上述入口// babel.config.js module.exports { presets: [ [babel/preset-env, { useBuiltIns: usage, corejs: 3.50, // 建议精确到 minor 版本 }], ], };然后在业务代码顶部显式import core-js/proposals/array-filtering-stage-1;详见 usage.md 的 Entry points 与 Babel 小节。注意 Babel 配置只解决稳定特性的按需注入早期提案仍需手动引入。源码剖析filterReject与filter共享同一套迭代引擎filterReject并非独立实现而是复用 core-js 内部统一的数组迭代引擎 internals/array-iteration.js。该文件通过一个createMethod(TYPE)工厂同时生成forEach、map、filter、some、every、find、findIndex与filterReject八个方法以整数类型码区分行为var IS_MAP TYPE 1; var IS_FILTER TYPE 2; var IS_SOME TYPE 3; var IS_EVERY TYPE 4; var IS_FIND_INDEX TYPE 6; var IS_FILTER_REJECT TYPE 7;模块底部将filterReject注册为类型码 7filterReject: createMethod(7)类型码 7 的分支逻辑在核心循环中filter类型码 2与filterReject类型码 7的区别只在回调返回真值还是假值时拷贝元素if (result) switch (TYPE) { // ... case 2: createProperty(target, resIndex, value); // filter真值保留 } else switch (TYPE) { // ... case 7: createProperty(target, resIndex, value); // filterReject假值保留 }也就是说两者共享相同的遍历骨架toObject装箱、lengthOfArrayLike取长度、bind(callbackfn, that)绑定上下文、跳过稀疏空洞仅拷贝条件取反。这也是为什么在引擎层面filterReject的复杂度和filter完全一致。数组模块封装入口模块 modules/esnext.array.filter-reject.js 只做两件事将filterReject以proto: true, forced: true的方式注册到Array.prototype并通过addToUnscopables(filterReject)将其加入Symbol.unscopables列表避免在with语句环境中产生标识符冲突$({ target: Array, proto: true, forced: true }, { filterReject: function filterReject(callbackfn /* , thisArg */) { return $filterReject(this, callbackfn, arguments.length 1 ? arguments[1] : undefined); } }); addToUnscopables(filterReject);TypedArray 模块封装TypedArray 版 modules/esnext.typed-array.filter-reject.js 同样复用array-iteration的filterReject但多了一步类型约束与同构重建exportTypedArrayMethod(filterReject, function filterReject(callbackfn /* , thisArg */) { var list $filterReject(aTypedArray(this), callbackfn, arguments.length 1 ? arguments[1] : undefined); return fromSameTypeAndList(this, list); }, true);aTypedArray(this)强制要求接收者是合法 TypedArray否则抛TypeError——这解释了测试中filterReject.call([0], ...)抛错的not generic行为TypedArray 方法不可用于普通数组fromSameTypeAndList走 internals/typed-array-from-same-type-and-list.js依据源实例的构造器重建同类型的新 TypedArray从而保证Int8Array过滤后仍是Int8Array。测试验证与兼容性数据仓库为该提案配置了完整的测试与兼容性检测单元测试tests/unit-global/esnext.array.filter-reject.js验证方法存在、arity 为 1、非枚举验证回调三参数与thisArg绑定验证混合类型数组过滤严格模式下对null/undefined接收者抛TypeError验证ToLength对负长度数组的处理{ length: -1, 0: 1 }不抛错验证Symbol.species。tests/unit-global/esnext.typed-array.filter-reject.js遍历全部 TypedArray 类型逐一断言方法存在、arity、原生外观、实例类型、值正确性、values/keys顺序、非通用性。tests/unit-pure/esnext.array.filter-reject.js对core-js-pure静态函数版做同等覆盖。兼容性探测tests/compat/tests.js 中为esnext.array.filter-reject与esnext.typed-array.filter-reject注册了能力探测函数用于core-js-compat按运行环境自动判断是否需要注入 polyfillesnext.array.filter-reject: function () { return [].filterReject; }, esnext.typed-array.filter-reject: function () { return Int8Array.prototype.filterReject; },实操示例在项目中启用与使用安装与项目其余依赖同理npm install --save core-js场景一全局版本全量启用提案// 入口文件顶部 import core-js/proposals/array-filtering-stage-1; // 业务代码 const numbers [10, 15, 20, 25, 30]; const oddsRejected numbers.filterReject(it it % 5 0); // []全部被剔除 const nonMultiplesOf10 numbers.filterReject(it it % 10 0); // [15, 25] const scores new Int16Array([90, 55, 70, 40, 88]); const passed scores.filterReject(it it 60); // Int16Array [90, 70, 88]场景二pure 版本避免污染全局import filterReject from core-js-pure/full/array/filter-reject; filterReject([1, 2, 3, q, {}, 4, true, 5], it typeof it ! number); // [1, 2, 3, 4, 5]场景三按方法最小化引入// 只需要数组版 import core-js/full/array/filter-reject; // 只需要 TypedArray 版 import core-js/full/typed-array/filter-reject;与既有filter的等价对照const list [1, 2, 3, 4, 5]; // 等价写法 list.filterReject(it it % 2); // [2, 4] list.filter(it !(it % 2)); // [2, 4] // 过滤不符合条件的元素是 filterReject 的天然语义 const products [ { name: A, stock: 0 }, { name: B, stock: 3 }, { name: C, stock: 0 }, ]; products.filterReject(p p.stock 0); // [{ name: B, stock: 3 }]使用注意事项提案阶段Array filtering目前处于 Stage 1early-stagefilterReject属于实验性 API接口在未来可能调整。生产环境使用时建议配合编译降级或做好运行时能力探测可用上文compat探测函数思路并在升级 core-js 时关注 CHANGELOG。命名取舍历史命名filterOut已废弃并计划在core-js4移除请统一使用filterReject。TypedArray 版本不可用于普通数组%TypedArray%.prototype.filterReject通过aTypedArray强校验接收者对普通数组调用会抛TypeError。返回值是新集合filterReject与原数组filter一样返回新数组/新 TypedArray不修改原集合TypedArray 结果始终与原实例同类型。入口选择常规场景使用proposals/、full/等公开入口modules/与internals/属于内部实现接口不稳定不应直接依赖。参考文件索引提案文档docs/web/docs/features/proposals/array-filtering.md提案入口packages/core-js/proposals/array-filtering-stage-1.js、packages/core-js/proposals/array-filtering.js模块实现packages/core-js/modules/esnext.array.filter-reject.js、packages/core-js/modules/esnext.typed-array.filter-reject.js、packages/core-js/modules/esnext.array.filter-out.js内部引擎packages/core-js/internals/array-iteration.js、packages/core-js/internals/typed-array-from-same-type-and-list.js入口封装packages/core-js/full/array/virtual/filter-reject.js、packages/core-js/full/instance/filter-reject.js、packages/core-js/full/typed-array/methods.js单元测试tests/unit-global/esnext.array.filter-reject.js、tests/unit-global/esnext.typed-array.filter-reject.js、tests/unit-pure/esnext.array.filter-reject.js兼容性探测tests/compat/tests.js使用文档docs/web/docs/usage.md【免费下载链接】core-jsStandard Library项目地址: https://gitcode.com/GitHub_Trending/co/core-js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
网站建设高端定制企业官网