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

相关推荐
字节高级特工3 分钟前
【C++】”如虎添翼“:模板初阶
java·c语言·前端·javascript·c++·学习·算法
小冻梨!!!27 分钟前
Spark,在shell中运行RDD程序
大数据·javascript·spark
大猫会长41 分钟前
lenis滑动插件的笔记
javascript
db_lnn_20211 小时前
【vue】全局组件及组件模块抽离
前端·javascript·vue.js
Qin_jiangshan1 小时前
vue实现进度条带指针
前端·javascript·vue.js
天高任鸟飞dyz1 小时前
tabs切换#
javascript·vue.js·elementui
菜鸟una1 小时前
【layout组件 与 路由镶嵌】vue3 后台管理系统
前端·vue.js·elementui·typescript
小张快跑。1 小时前
【Vue3】使用vite创建Vue3工程、Vue3基本语法讲解
前端·前端框架·vue3·vite
Zhen (Evan) Wang1 小时前
.NET 8 API 实现websocket,并在前端angular实现调用
前端·websocket·.net
星空寻流年2 小时前
css3响应式布局
前端·css·css3