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

相关推荐
掘金安东尼15 分钟前
上周前端发生哪些新鲜事儿? #407
前端·面试·github
小谭鸡米花24 分钟前
ECharts各类炫酷图表/3D柱形图
前端·javascript·echarts·大屏端
郝晨妤29 分钟前
【鸿蒙5.0】向用户申请麦克风授权
linux·服务器·前端·华为·harmonyos·鸿蒙
神秘代码行者39 分钟前
使用 contenteditable 属性实现网页内容可编辑化
前端·html5
小鱼人爱编程40 分钟前
Look My Eyes 最新IDEA快速搭建Java Web工程的两种方式
java·前端·后端
郝晨妤41 分钟前
【鸿蒙5.0】鸿蒙登录界面 web嵌入(隐私页面加载)
前端·华为·harmonyos
小鱼人爱编程1 小时前
当上小组长的第3天,我裁掉了2年老员工
前端·后端·面试
晓得迷路了1 小时前
栗子前端技术周刊第 74 期 - 2025 Vue.js 现状报告、Element Plus X、Material UI v7...
前端·javascript·vue.js
知识分享小能手1 小时前
CSS3学习教程,从入门到精通, CSS3 变形效果(2D 和 3D)的详细语法知识点及案例代码(22)
前端·javascript·css·学习·3d·css3·html5
花之亡灵1 小时前
.net 6 + vue3中使用SignaIR实现双向通信功能
前端·javascript·笔记·websocket·.net·信息与通信