ARTICLE DETAIL

资讯详情

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

es-toolkit 兼容层 keysIn 详解:获取含继承属性的全部枚举键名

es-toolkit 兼容层 keysIn 详解:获取含继承属性的全部枚举键名 es-toolkit 兼容层 keysIn 详解获取含继承属性的全部枚举键名【免费下载链接】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-toolkitkeysIn是 es-toolkit 兼容层es-toolkit/compat为对齐 lodash 而提供的对象工具函数它返回对象自身与原型链上所有可枚举属性名的字符串数组。本文将以 keysIn 兼容文档 为骨架结合 keysIn 源码 与其 完整测试用例讲解该函数的基本用法、对数组 / 类数组 / 继承属性 / 空值的特殊处理以及其底层实现原理与性能注意事项帮助你在迁移 lodash 代码或日常取键场景中做出正确选择。功能概览keysIn 解决什么问题keysIn的作用是返回一个对象的所有可枚举属性名包括自身属性与继承属性组成的字符串数组。const allKeys keysIn(object);它与keys的核心区别在于keys见 keys 源码只返回自身可枚举属性而keysIn会沿着原型链一路向上把继承到的可枚举属性也一并纳入结果。这与 lodash 的_.keysIn行为保持一致方便 lodash 老项目平滑迁移。注意该函数仅返回字符串键的属性名Symbol 键不在其中且与 lodash 相同结果数组不保证键的迭代顺序。基本用法在es-toolkit/compat入口下导入即可使用import { keysIn } from es-toolkit/compat; // 基本对象的键 const object { a: 1, b: 2 }; keysIn(object); // [a, b] // 数组的索引 const array [1, 2, 3]; keysIn(array); // [0, 1, 2] // 字符串的索引 keysIn(hello); // [0, 1, 2, 3, 4]值得注意的两个细节数组返回的是字符串形式的索引0、1、2而不是数字下标字符串原语会被自动装箱为 String 对象从而返回字符位置索引。这一点在 keysIn.spec.ts 中有专门用例验证且字符串对象上自定义的属性如Object(a).a 1也会被返回。参数与返回值参数objectany要获取键的对象。返回值string[]包含自身与继承的所有可枚举属性名字符串键的数组。继承属性与 keys 的本质差异keysIn会包含原型链上可枚举的继承属性这是它区别于keys的最关键行为import { keysIn } from es-toolkit/compat; function Foo() { this.a 1; this.b 2; } Foo.prototype.c 3; keysIn(new Foo()); // [a, b, c]包含原型属性 c // constructor 会被排除 class MyClass { constructor() { this.prop 1; } method() {} } MyClass.prototype.inherited 2; keysIn(new MyClass()); // [prop, method, inherited]constructor 被排除两个要点需要特别说明原型上的普通属性会被包含Foo.prototype.c 3后实例new Foo()的键自然多出c。constructor被排除当传入的对象本身是一个原型对象prototype时结果中不会出现constructor。测试用例 keysIn.spec.ts 覆盖了多种原型场景包括Foo.prototype、显式赋值{ constructor: Foo, a: 1 }以及伪造的Fake.prototype验证constructor的过滤逻辑仅在原型对象上生效。这一排除 constructor的行为并非在普通对象上硬性过滤而是由源码中的isPrototype判定触发见下文源码剖析。类数组对象的特殊处理keysIn对类数组array-like对象走专门的分支逻辑与普通对象不同import { keysIn } from es-toolkit/compat; // TypedArray const typedArray new Uint8Array([1, 2, 3]); keysIn(typedArray); // [0, 1, 2]buffer、byteLength 等被排除 // arguments 对象 function example() { return keysIn(arguments); } example(a, b, c); // [0, 1, 2]行为细节包括TypedArray会剔除buffer、byteLength、byteOffset这些非索引的枚举属性对应测试 keysIn.spec.tsarguments 对象返回[0, 1, 2]若在 arguments 上添加自定义属性a结果会变为[0, 1, 2, a]见 keysIn.spec.ts稀疏数组按稠密处理const arr [1]; arr[2] 3;会返回[0, 1, 2]缺失的下标也被补齐keysIn.spec.ts类数组对象保留 length{ 0: a, length: 1 }返回[0, length]keysIn.spec.tsBuffer不会返回offset、parentkeysIn.spec.ts数组上的自定义属性也会保留[1].a 1返回[0, a]且Array.prototype.a 1这类继承属性同样会被包含keysIn.spec.ts。null / undefined 的安全处理与 lodash 一致keysIn对空值不会抛错而是返回空数组import { keysIn } from es-toolkit/compat; keysIn(null); // [] keysIn(undefined); // []测试 keysIn.spec.ts 还额外验证了即使此时在Object.prototype上挂载了属性模拟污染环境keysIn(null)、keysIn(undefined)以及无参调用依然稳定返回[]不会受原型污染干扰。源码实现剖析从 keysIn 源码 可以看到keysIn采用按类型分流的策略实现export function keysIn(object?: any): string[] { if (object null) { return []; } switch (typeof object) { case object: case function: { if (isArrayLike(object)) { return arrayLikeKeysIn(object); } if (isPrototype(object)) { return prototypeKeysIn(object); } return keysInImpl(object); } default: { return keysInImpl(Object(object)); } } }核心路径可拆解为四层空值短路object null直接返回[]类数组分支通过 isArrayLike基于length是否为合法长度且非函数判定后进入arrayLikeKeysIn原型对象分支通过 isPrototype比对value是否等于其constructor.prototype判定后进入prototypeKeysIn过滤掉constructor键默认分支keysInImpl直接使用for...in循环收集所有可枚举键含继承而对原始类型数字、字符串、布尔、Symbol、BigInt则先执行Object(object)装箱转换。在arrayLikeKeysInkeysIn.ts内部先用times生成全部下标字符串再用Set建立应排除的键集合对 Buffer 额外加入offset、parent对 TypedArray 额外加入buffer、byteLength、byteOffset随后通过for...in收集继承键并去重最后按是否为真数组决定是否用Object.hasOwn过滤缺失下标。整个设计目标是在 lodash 兼容语义稠密化、排除内建非索引属性、含继承键与可读性之间取得平衡。性能注意事项何时不该用它官方文档在函数开头就给出了明确的警告——建议优先使用for...in循环或Object.keys()keysIn由于包含类数组处理、原型链遍历等复杂逻辑运行速度较慢。请改用更快的现代写法for...in循环或按需使用Object.keys()。在 keysIn 源码 中可以看到keysInImpl本质上就是for...in但外层还叠加了isArrayLike、isPrototype、isTypedArray、isBuffer等多重判定以及下标数组生成与Set去重这些都会带来额外开销。因此在追求性能的热路径代码中只需自身键 → 用Object.keys(obj)需要含继承的可枚举键 → 直接写for (const key in obj)循环。keysIn更适合用于与 lodash 逐字节对齐的兼容场景或需要其类数组特殊语义如 TypedArray 排除buffer等的场合。与相关函数的关系在 es-toolkit 兼容层中keysIn与以下函数构成一个取键/取值家族可组合使用keys只返回自身可枚举键见 keys 文档 与 keys 源码内部同样复用了arrayLikeKeys与isPrototype逻辑区别仅在于继承属性的取舍valuesIn返回含继承属性的所有可枚举值valuesIn.tstoPairsIn返回含继承属性的[key, value]键值对数组toPairsIn.tsassignIn/assignInWith合并对象时同样遍历含继承的可枚举属性assignIn.tspickBy/omit/omitBy在过滤属性时也会用到含继承键的遍历逻辑pickBy.ts。这些函数共同构成了全量遍历属性own inherited的兼容语义族。当你在迁移 lodash 代码时发现_.keysIn、_.valuesIn、_.toPairsIn等成对出现可以直接用 es-toolkit 的对应函数无缝替换。小结keysIn是 es-toolkit 兼容层中语义最宽的取键函数它返回自身 原型链上的全部可枚举字符串键对数组、字符串、arguments、TypedArray 等类数组输入做专门的稠密化与属性过滤处理对null/undefined返回空数组并对原型对象排除constructor。其源码通过空值短路 → 类数组分支 → 原型分支 → 默认for...in的四级分流在 lodash 兼容行为与现代实现之间做了清晰切分。日常开发中除非需要与 lodash 行为严格对齐或依赖其类数组特殊语义否则更推荐直接使用for...in或Object.keys()以获取更好的性能。【免费下载链接】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),仅供参考
返回列表