十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

es-toolkit 的 forIn 兼容实现:遍历对象全部属性(含原型链继承属性)的完整指南

es-toolkit 的 forIn 兼容实现:遍历对象全部属性(含原型链继承属性)的完整指南 es-toolkit 的 forIn 兼容实现遍历对象全部属性含原型链继承属性的完整指南【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit导读本文围绕 es-toolkit 的 Lodash 兼容入口es-toolkit/compat中的forIn函数展开讲解如何在保持 Lodash 调用习惯的前提下遍历一个对象自身的全部可枚举字符串属性以及通过原型链继承而来的属性并支持通过返回false提前终止遍历。读完本文你将掌握forIn的完整签名、默认行为、源码级实现原理含对null/undefined的兜底处理与默认identity迭代器以及它与forOwn、forInRight的差异和适合替代它的现代写法。一、forIn 是什么forIn是 es-toolkit/compat 兼容层提供的函数它的定位与 Lodash 同名函数保持一致遍历一个对象的所有属性包括通过原型链继承的属性并对每个属性调用传入的iteratee回调函数。它只遍历字符串键的属性不包含 Symbol 键。从源码实现看它的核心就是一个包装了for...in循环的封装// src/compat/object/forIn.ts export function forInT( object: T | null | undefined, iteratee: (value: T[keyof T], key: string, collection: T) any identity ): T | null | undefined { if (object null) { return object; } for (const key in object) { const result iteratee(object[key as keyof T], key, object); if (result false) { break; } } return object; }可见整个实现只有几行逻辑非常直白先处理空值再借助原生for...in天然会遍历原型链上可枚举属性的特性完成迭代并在回调返回false时break提前终止。二、基本用法与完整示例函数签名const result forIn(obj, iteratee);forIn(object, iteratee)遍历对象的所有属性并调用iteratee函数。它不只遍历对象自身的属性还会遍历通过原型链继承而来的属性。如果iteratee函数返回false遍历会立即停止。示例一遍历对象全部属性import { forIn } from es-toolkit/compat; const obj { a: 1, b: 2 }; forIn(obj, (value, key) { console.log(key, value); }); // Output: a 1, b 2示例二遍历包含继承属性的对象function Parent() { this.inherited value; } Parent.prototype.protoProperty proto; const child new Parent(); child.own ownValue; forIn(child, (value, key) { console.log(key, value); }); // Output: inherited value, own ownValue, protoProperty proto上面的输出顺序正是for...in的行为先遍历实例自身的可枚举属性inherited、own再沿原型链向上遍历原型上的可枚举属性protoProperty。示例三基于条件提前终止forIn(obj, (value, key) { console.log(key, value); return key ! a; // Stop after a }); // Output: a 1注意这里的终止条件是严格返回false回调只有返回布尔值false才会中断循环返回undefined、0、null等其他假值都不会中断。这一点在源码中体现得很明确——判断条件是result false。空值处理原样返回当传入null或undefined时forIn不会报错而是直接原样返回import { forIn } from es-toolkit/compat; forIn(null, iteratee); // null forIn(undefined, iteratee); // undefined源码第一行if (object null) return object;使用宽松相等判断一次性同时兜住null和undefined这正对应了类型签名中的T | null | undefined分支。三、参数与返回值详解项说明objectT \| null \| undefined要遍历的对象。传入null或undefined时原样返回不调用迭代器iteratee(value: T[keyof T], key: string, collection: T) any可选每次迭代调用的回调接收三个参数当前属性值value、属性键key字符串、被遍历的整个对象collection。默认值为identity函数原样返回入参。返回false时提前终止遍历返回值T \| null \| undefined返回原始对象本身几个值得强调的细节回调参数顺序与 Lodash 一致依次为(value, key, collection)。第三个参数collection可以让你在回调内部对原对象进行读写测试用例中就展示了这一点见 forIn.spec.ts回调里通过collection[key] 3修改原对象后返回false断言结果obj变为{ a: 3, b: 2 }证明中断后其余属性不再被处理。默认迭代器当第二个参数省略时默认使用identity函数。这意味着forIn(obj)依然合法只是遍历本身不产生任何副作用。返回值可链式使用由于始终返回原对象你可以把forIn的返回值继续传递给其他调用符合 Lodash 的链式风格预期。四、源码级原理剖析1. 依赖的原生能力for...in 与原型链forIn之所以能覆盖继承属性靠的是 JavaScript 原生for...in的语义它会枚举对象自身及原型链上所有可枚举的字符串属性。源码 forIn.ts 直接使用for (const key in object)没有任何额外的手动原型链遍历因此实现既短小又能与 Lodash 行为对齐。2. 默认 iteratee 的引入源码顶部import { identity } from ../../function/identity.ts;并在参数默认值处使用iteratee: ... identity。这意味着即使不传回调类型签名也能保持完整T[keyof T]的取值、string键、原对象三者不会出现undefined回调导致的运行时错误。3. 早停机制的语义早停的判断是if (result false) break;forIn.ts。这里使用严格等于false与!result截然不同——这是兼容 Lodash 语义的关键细节只有显式返回布尔false才会中断。五、与相关函数的对比forIn vs forOwn是否包含继承属性forIn遍历自身属性 原型链继承属性本文主角。forOwn只遍历对象自身的可枚举字符串属性不包含继承属性也不包含 Symbol 键。其实现 forOwn.ts 先通过keysToolkit(object)获取自身键列表再用普通for循环遍历。两者的iteratee签名、默认identity、null/undefined兜底、返回false早停的语义完全一致唯一区别是键的来源范围。forIn vs forInRight遍历方向forIn正序遍历for...in原生顺序。forInRight逆序遍历。其实现 forInRight.ts 先通过for...in把键收集进数组再从数组末尾向前迭代从而保证与正向遍历恰好相反的访问顺序。forIn直接遍历即可forInRight则需要一次额外的键收集这是两者实现上的主要差别。与 es-toolkit 严格入口的差异forIn位于 src/compat 兼容层入口文件在 compat.ts按export { forIn } from ./object/forIn.ts;导出它刻意复刻 Lodash 1:1 的接口与行为包括隐式类型容忍、多参数形态等。如果你不使用 Lodash官方建议优先使用更现代、类型更严格的es-toolkit主入口而不是compat。六、性能注意事项与更现代的替代方案官方文档对forIn给出了明确的性能警告由于它需要处理null/undefined、设置默认iteratee等额外逻辑运行速度较慢。推荐直接用更快、更现代的原生写法替代// 只遍历自身属性 Object.keys(obj).forEach((key) { console.log(key, obj[key]); }); // 需要包含原型链上的可枚举属性时 for (const key in obj) { console.log(key, obj[key]); }如果你的遍历目标本身就不需要继承属性绝大多数场景都是如此Object.keysforEach是更优选择只有在你确实需要兼容原型链属性、并且希望保持 Lodash 调用习惯例如正在迁移旧代码库时才建议继续使用forIn。七、测试验证与兼容性承诺forIn.spec.ts 覆盖了forIn的全部关键行为可作为你理解和使用该函数的权威参考遍历含继承属性的对象断言收集到的键集合为[a, b]L5-L18传入null返回nullL20-L22传入undefined返回undefinedL24-L26回调返回false时提前终止且已处理的属性修改生效L28-L38。根据 compat 说明es-toolkit/compat自 v1.39.3 起通过 Lodash 自身的测试套件实现 100% 行为兼容因此你从lodash/lodash-es迁移到es-toolkit/compat时forIn的调用点可以原样保留无需改写。迁移路径通常是先把导入路径从lodash换成es-toolkit/compat之后再逐步清理调用点、切换到更精简的严格入口。【免费下载链接】es-toolkitA modern JavaScript utility library thats 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表