Lodash 源码阅读-getAllKeys
功能概述
getAllKeys
是 Lodash 库中的一个内部工具函数,它的主要作用是创建一个包含目标对象自身所有可枚举属性名和 Symbol 属性的数组。与 keys
函数不同,getAllKeys
不仅返回普通的字符串键,还会返回 Symbol 类型的键,使其成为获取对象完整键集合的有力工具。
前置学习
依赖关系
getAllKeys
函数依赖以下几个函数和变量:
- baseGetAllKeys:一个基础实现函数,用于获取对象的属性名和 Symbol
- keys:获取对象自身的可枚举属性名
- getSymbols:获取对象自身的可枚举 Symbol 属性
- arrayPush:将一个数组的元素添加到另一个数组中
技术知识
- ES6 Symbol:JavaScript 中的原始数据类型,表示唯一的标识符
- 可枚举属性:JavaScript 对象的属性可以是可枚举的或不可枚举的,可枚举属性可以通过 for...in 循环遍历
- 函数组合:通过组合多个函数来实现复杂功能的编程模式
源码实现
javascript
/**
* Creates an array of own enumerable property names and symbols of `object`.
*
* @private
* @param {Object} object The object to query.
* @returns {Array} Returns the array of property names and symbols.
*/
function getAllKeys(object) {
return baseGetAllKeys(object, keys, getSymbols);
}
实现思路
getAllKeys
函数的实现思路非常简洁明了,它通过调用 baseGetAllKeys
函数,并传入三个参数:
- 要查询的对象
object
- 获取对象属性名的函数
keys
- 获取对象 Symbol 属性的函数
getSymbols
baseGetAllKeys
函数会先使用 keys
函数获取对象的所有可枚举属性名,然后使用 getSymbols
函数获取对象的所有可枚举 Symbol 属性,最后将两者合并返回。这种实现方式通过函数组合的方式,将获取不同类型键的逻辑分离,使代码更加清晰和可维护。
源码解析
函数签名
javascript
function getAllKeys(object) {
函数接收一个参数:
object
:要查询的对象,可以是任何类型的值
调用 baseGetAllKeys
javascript
return baseGetAllKeys(object, keys, getSymbols);
这行代码是函数的核心,它调用 baseGetAllKeys
函数,并传入三个参数:
object
:要查询的对象keys
:获取对象属性名的函数getSymbols
:获取对象 Symbol 属性的函数
baseGetAllKeys 的实现
javascript
function baseGetAllKeys(object, keysFunc, symbolsFunc) {
var result = keysFunc(object);
return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
}
baseGetAllKeys
函数的实现包括以下步骤:
- 调用
keysFunc
(即keys
函数)获取对象的所有可枚举属性名,并将结果存储在result
变量中 - 检查
object
是否为数组:- 如果是数组,直接返回
result
(因为数组通常不会有 Symbol 属性) - 如果不是数组,调用
symbolsFunc
(即getSymbols
函数)获取对象的所有可枚举 Symbol 属性,然后使用arrayPush
将其添加到result
中,最后返回合并后的结果
- 如果是数组,直接返回
与其他函数的比较
getAllKeys
函数与 Lodash 中的其他类似函数有一些重要区别:
-
keys vs getAllKeys:
keys
只返回对象自身的可枚举字符串属性名getAllKeys
返回对象自身的可枚举字符串属性名和 Symbol 属性
javascriptconst sym = Symbol("test"); const obj = { a: 1, [sym]: 2 }; console.log(_.keys(obj)); // ['a'] console.log(_.getAllKeys(obj)); // ['a', Symbol(test)]
-
Object.keys vs getAllKeys:
Object.keys
只返回对象自身的可枚举字符串属性名getAllKeys
返回对象自身的可枚举字符串属性名和 Symbol 属性
javascriptconst sym = Symbol("test"); const obj = { a: 1, [sym]: 2 }; console.log(Object.keys(obj)); // ['a'] console.log(_.getAllKeys(obj)); // ['a', Symbol(test)]
-
Object.getOwnPropertyNames vs getAllKeys:
Object.getOwnPropertyNames
返回对象自身的所有字符串属性名(包括不可枚举的)getAllKeys
只返回对象自身的可枚举字符串属性名和 Symbol 属性
javascriptconst obj = {}; Object.defineProperty(obj, "a", { value: 1, enumerable: false }); const sym = Symbol("test"); obj[sym] = 2; console.log(Object.getOwnPropertyNames(obj)); // ['a'] console.log(_.getAllKeys(obj)); // [Symbol(test)]
总结
getAllKeys
是 Lodash 中一个强大而实用的内部工具函数,它通过组合 keys
和 getSymbols
函数,提供了一种获取对象所有可枚举键(包括 Symbol)的简洁方法。
这个函数的设计体现了几个重要的软件工程原则:
- 单一职责:函数只负责一件事情 - 获取对象的所有可枚举键
- 函数组合:通过组合多个专门的函数来实现复杂功能
- 代码复用 :利用已有的
baseGetAllKeys
、keys
和getSymbols
函数,避免重复代码 - 抽象层次:提供了比原生方法更高级的抽象,简化了获取所有类型键的过程