Lodash 源码阅读-keysIn
功能概述
keysIn
是 Lodash 中的一个实用函数,用于获取对象的所有可枚举属性名,包括对象自身的属性和从原型链继承的属性。与 keys
函数(只返回对象自身属性)不同,keysIn
会遍历整个原型链,返回所有可访问的属性名数组。
这个函数是处理对象属性时非常有用的工具,特别是在需要考虑继承属性的场景中。
前置学习
依赖函数
- baseKeysIn:内部实现函数,用于处理复杂对象的属性获取
- isArrayLike:检查值是否类似数组结构的辅助函数
- arrayLikeKeys:处理类数组对象的属性获取,第二个参数为 true 时包含继承属性
源码实现
javascript
function keysIn(object) {
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
}
实现思路
keysIn
函数的实现思路非常简洁明了:
-
判断输入值是否为类数组对象
- 如果是类数组对象,使用
arrayLikeKeys
函数处理,并传入true
参数表示包含继承的属性 - 这种情况适用于数组、字符串、arguments 对象、类型化数组(如 Int8Array)等具有 length 属性且 length 为非负整数的数据结构
- 如果是类数组对象,使用
-
如果不是类数组对象,调用
baseKeysIn
函数处理普通对象baseKeysIn
会处理所有可枚举的属性,包括继承的
源码解析
让我们逐行分析 keysIn
函数的实现:
javascript
function keysIn(object) {
函数定义,接收一个 object
参数,这个参数可以是任何类型的值(包括 null 和 undefined)。
javascript
return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
这是一个三元条件表达式,根据 object
是否为类数组对象进行不同的处理:
类数组对象处理
如果 isArrayLike(object)
返回 true
,说明 object
是一个类数组对象,那么调用 arrayLikeKeys(object, true)
处理。
arrayLikeKeys
函数专门用于处理类数组对象的属性获取,第二个参数 true
表示需要包含继承的属性。对于类数组对象,它的处理逻辑如下:
- 创建一个空数组用于存储结果
- 遍历类数组对象的索引,将每个有效索引添加到结果数组
- 如果第二个参数为
true
,则还会通过 for...in 循环获取继承的属性 - 返回最终的属性名数组
示例:
javascript
// 类数组对象示例
const str = "hello";
console.log(_.keysIn(str)); // ['0', '1', '2', '3', '4', ...继承的属性]
const arr = [1, 2, 3];
console.log(_.keysIn(arr)); // ['0', '1', '2', 'length', ...Array 原型上的方法名]
普通对象处理
如果 isArrayLike(object)
返回 false
,说明 object
是普通对象(或非对象值),那么调用 baseKeysIn(object)
处理。
baseKeysIn
函数的实现我们在《Lodash 源码阅读-baseKeysIn》中已经详细分析过,它会:
- 检查输入值是否为对象
- 使用 for...in 循环遍历所有可枚举属性(包括继承的)
- 特殊处理 constructor 属性
- 返回包含所有属性名的数组
示例:
javascript
// 普通对象示例
const obj = { a: 1, b: 2 };
console.log(_.keysIn(obj)); // ['a', 'b', ...Object 原型上的可枚举属性]
// 自定义原型链
const proto = { z: 3 };
const child = Object.create(proto);
child.x = 1;
child.y = 2;
console.log(_.keysIn(child)); // ['x', 'y', 'z', ...Object 原型上的可枚举属性]
与 keys 函数的区别
keysIn
和 Lodash 的 keys
函数是一对相关但功能不同的函数:
javascript
// keys 函数(只返回自身属性)
_.keys({ a: 1, b: 2 }); // ['a', 'b']
// keysIn 函数(返回自身和继承属性)
_.keysIn({ a: 1, b: 2 }); // ['a', 'b', ...继承的可枚举属性]
主要区别:
keys
仅返回对象自身的可枚举属性,不包括继承的属性keysIn
返回对象自身和继承的所有可枚举属性keys
在内部使用baseKeys
,而keysIn
使用baseKeysIn
keys
的行为类似于Object.keys()
,而keysIn
的行为类似于使用 for...in 循环
总结
keysIn
是 Lodash 库中一个用于获取对象所有可枚举属性名(包括继承的)的实用函数。通过对不同类型输入的智能处理,它提供了一种简单而强大的方式来访问对象的完整属性集。
keysIn
函数在以下场景特别有用:
- 深度克隆需要保留原型链属性的对象
- 合并配置对象时考虑继承的默认值
- 验证包括继承属性在内的所有属性
- 检查对象(包括其原型链)是否包含特定属性