Lodash源码阅读-baseKeys

功能概述

baseKeys 函数是 Lodash 中的一个内部工具函数,主要用于获取对象自身的可枚举属性名。它是 _.keys 方法的基础实现,通过巧妙处理原型对象的特殊情况,确保了在各种场景下都能正确获取对象的键名。

前置学习

  • isPrototype
  • nativeKeys

源码实现

js 复制代码
function baseKeys(object) {
    if (!isPrototype(object)) {
        return nativeKeys(object);
    }
    var result = [];
    for (var key in Object(object)) {
        if (hasOwnProperty.call(object, key) && key != "constructor") {
            result.push(key);
        }
    }
    return result;
}

实现原理解析

原理概述

baseKeys 函数的核心思想是获取对象自身的可枚举属性名,同时处理原型对象的特殊情况。它采用了两种不同的策略:

  1. 对于普通对象:直接使用 nativeKeys(即 Object.keys 的包装)获取属性名
  2. 对于原型对象:手动遍历对象的所有可枚举属性,筛选出自身属性并排除 constructor 属性

这种设计确保了在处理原型对象时不会出现意外行为,同时在处理普通对象时保持了高效性。

代码解析

1. 原型对象检测

js 复制代码
if (!isPrototype(object)) {
    return nativeKeys(object);
}

函数首先通过 isPrototype 检查传入的对象是否为原型对象:

  • 如果不是原型对象,直接使用 nativeKeys 获取属性名
  • 这是一种性能优化,因为大多数情况下我们处理的是普通对象

示例:

js 复制代码
// 普通对象不是原型对象
const obj = { a: 1, b: 2 };
console.log(isPrototype(obj)); // false

// 构造函数的 prototype 属性是原型对象
function Person() {}
console.log(isPrototype(Person.prototype)); // true

// 内置对象的原型也是原型对象
console.log(isPrototype(Array.prototype)); // true

2. 使用 nativeKeys 处理普通对象

对于普通对象,函数使用 nativeKeys 获取属性名:

js 复制代码
return nativeKeys(object);

nativeKeys 是对 Object.keys 的包装。

3. 手动处理原型对象

对于原型对象,函数采用手动遍历的方式:

js 复制代码
var result = [];
for (var key in Object(object)) {
    if (hasOwnProperty.call(object, key) && key != "constructor") {
        result.push(key);
    }
}
return result;

这段代码做了几件重要的事情:

  1. 使用 Object(object) 确保即使传入的是原始值也能正确处理
  2. 使用 for...in 循环遍历对象的所有可枚举属性(包括继承的)
  3. 通过 hasOwnProperty.call(object, key) 筛选出对象自身的属性
  4. 排除 constructor 属性,因为它通常不是我们关心的数据属性
  5. 将符合条件的属性名添加到结果数组中

示例:

js 复制代码
// 创建一个原型对象
function MyClass() {}
MyClass.prototype.a = 1;
MyClass.prototype.b = 2;

// 使用 baseKeys 获取属性名
console.log(baseKeys(MyClass.prototype)); // ['a', 'b']

// 注意 constructor 属性被排除了
console.log("constructor" in MyClass.prototype); // true

注意事项

  1. baseKeys 只返回对象自身的可枚举属性,不包含原型链上的属性
js 复制代码
const parent = { x: 1 };
const child = Object.create(parent);
child.y = 2;

console.log(baseKeys(child)); // ['y']
// x 不会被返回,因为它在原型链上
  1. baseKeys 会排除 constructor 属性(当处理原型对象时)
js 复制代码
function Custom() {}
Custom.prototype.method = function () {};
console.log(baseKeys(Custom.prototype)); // ['method']
// constructor 属性被排除了
  1. Symbol 类型的属性会被忽略
js 复制代码
const obj = {
    [Symbol("a")]: 1,
    b: 2,
};
console.log(baseKeys(obj)); // ['b']
// Symbol 属性不会出现在结果中

总结

baseKeys 函数通过区分普通对象和原型对象,采用不同的策略获取对象自身的可枚举属性名。它的主要特点是:

  1. 性能优化:对普通对象使用原生的 Object.keys 方法
  2. 特殊处理:对原型对象进行手动遍历和筛选
  3. 安全处理:通过 Object() 转换确保能处理各种输入
  4. 排除干扰:特别排除了原型对象上的 constructor 属性

这个函数在 Lodash 中被广泛用作获取对象属性的基础工具,是 _.keys 等方法的核心实现。

相关推荐
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60618 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了8 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅9 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅9 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment9 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼10 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax