Lodash源码阅读-keys

Lodash 源码阅读-keys

功能概述

keys 是 Lodash 库中的一个核心函数,用于获取对象自身的可枚举属性名称。它能够处理各种类型的对象,包括普通对象、数组、类数组对象等,并返回一个包含所有属性名的数组。

前置学习

依赖函数

keys 函数依赖以下几个 Lodash 内部函数:

  • isArrayLike:检查值是否为类数组对象
  • arrayLikeKeys:获取类数组对象的可枚举属性名
  • baseKeys:获取非类数组对象的可枚举属性名

技术知识

  • 可枚举属性:JavaScript 对象的属性可以是可枚举的或不可枚举的,可枚举属性可以通过 for...in 循环遍历
  • 类数组对象:具有 length 属性和索引元素的对象,如数组、arguments、DOM 集合等
  • Object.keys:ES5 引入的原生方法,用于获取对象自身的可枚举属性名
  • hasOwnProperty:用于检查属性是否为对象自身的属性(而非继承的)

源码实现

javascript 复制代码
/**
 * Creates an array of the own enumerable property names of `object`.
 *
 * **Note:** Non-object values are coerced to objects. See the
 * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
 * for more details.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Object
 * @param {Object} object The object to query.
 * @returns {Array} Returns the array of property names.
 * @example
 *
 * function Foo() {
 *   this.a = 1;
 *   this.b = 2;
 * }
 *
 * Foo.prototype.c = 3;
 *
 * _.keys(new Foo);
 * // => ['a', 'b'] (iteration order is not guaranteed)
 *
 * _.keys('hi');
 * // => ['0', '1']
 */
function keys(object) {
  return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
}

实现思路

keys 函数的实现思路非常简洁明了,可以分为以下几个步骤:

  1. 类型判断:首先判断传入的对象是否为类数组对象
  2. 分支处理
    • 如果是类数组对象,使用 arrayLikeKeys 获取属性名
    • 如果不是类数组对象,使用 baseKeys 获取属性名
  3. 返回结果:返回包含所有属性名的数组

这种实现方式既简洁又高效,通过区分不同类型的对象采用不同的处理策略,确保了在各种情况下都能正确获取对象的属性名。

源码解析

函数签名

javascript 复制代码
function keys(object) {

函数接收一个参数:

  • object:要查询的对象,可以是任何类型的值

类型判断和分支处理

javascript 复制代码
return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);

这行代码是函数的核心,它根据对象的类型选择不同的处理方式:

  1. isArrayLike(object) :判断 object 是否为类数组对象

    • 类数组对象需满足:非函数、有 length 属性、length 为非负整数且不超过最大安全整数
  2. arrayLikeKeys(object) :如果是类数组对象,使用 arrayLikeKeys 获取属性名

    • 这个函数会特殊处理数组、arguments、Buffer、TypedArray 等类数组对象
    • 对于类数组对象,它会预先创建包含所有索引的数组,然后添加其他非索引属性
  3. baseKeys(object) :如果不是类数组对象,使用 baseKeys 获取属性名

    • 这个函数会处理普通对象,通常使用 Object.keys 的包装
    • 对于原型对象,它会手动遍历并筛选出自身的可枚举属性

与其他函数的关系

keys 函数与 Lodash 中的其他函数有密切的关系:

  1. keysIn :与 keys 类似,但包含继承的属性

    javascript 复制代码
    function Foo() {
      this.a = 1;
      this.b = 2;
    }
    
    Foo.prototype.c = 3;
    
    const foo = new Foo();
    console.log(_.keys(foo)); // ['a', 'b']
    console.log(_.keysIn(foo)); // ['a', 'b', 'c']
  2. values :获取对象的所有值,内部使用 keys 获取属性名

    javascript 复制代码
    function values(object) {
      return object == null ? [] : baseValues(object, keys(object));
    }
  3. entries/toPairs :将对象转换为键值对数组,内部使用 keys 获取属性名

    javascript 复制代码
    function toPairs(object) {
      return object == null ? [] : baseToPairs(object, keys(object));
    }
  4. forEach/map/filter 等集合操作函数 :这些函数在处理对象时,通常使用 keys 获取属性名进行遍历

  5. assign/merge 等对象操作函数 :这些函数在合并对象时,通常使用 keys 获取源对象的属性名

与原生方法的比较

keys 函数与 JavaScript 原生的 Object.keys 方法有一些区别:

  1. 处理非对象值

    • Object.keys 会在传入非对象值时抛出错误
    • _.keys 会将非对象值转换为对象再处理
    javascript 复制代码
    Object.keys("hi"); // ['0', '1']
    Object.keys(123); // TypeError: 123 is not an object
    
    _.keys("hi"); // ['0', '1']
    _.keys(123); // []
  2. 处理类数组对象

    • Object.keys 对所有对象的处理方式相同
    • _.keys 对类数组对象有特殊的处理逻辑,使用 arrayLikeKeys 函数
  3. 处理原型对象

    • Object.keys 在处理原型对象时可能会包含 constructor 属性
    • _.keys 通过 baseKeys 函数特殊处理原型对象,排除 constructor 属性

总结

keys 是 Lodash 中一个核心的工具函数,用于获取对象自身的可枚举属性名。它通过区分不同类型的对象采用不同的处理策略,确保了在各种情况下都能正确获取对象的属性名。

相关推荐
kidding7235 分钟前
gitee新的仓库,Vscode创建新的分支详细步骤
前端·gitee·在仓库创建新的分支
听风吹等浪起8 分钟前
基于html实现的课题随机点名
前端·html
leluckys14 分钟前
flutter 专题 六十三 Flutter入门与实战作者:xiangzhihong8Fluter 应用调试
前端·javascript·flutter
kidding72328 分钟前
微信小程序怎么分包步骤(包括怎么主包跳转到分包)
前端·微信小程序·前端开发·分包·wx.navigateto·subpackages
微学AI42 分钟前
详细介绍:MCP(大模型上下文协议)的架构与组件,以及MCP的开发实践
前端·人工智能·深度学习·架构·llm·mcp
liangshanbo12151 小时前
CSS 包含块
前端·css
Mitchell_C1 小时前
语义化 HTML (Semantic HTML)
前端·html
倒霉男孩1 小时前
CSS文本属性
前端·css
shoa_top1 小时前
JavaScript 数组方法总结
javascript
晚风3081 小时前
前端
前端