Lodash源码阅读-nativeKeysIn

Lodash 源码阅读-nativeKeysIn

功能概述

nativeKeysIn 是 Lodash 中的一个内部工具函数,用于获取对象的所有可枚举属性名(包括自身和继承的属性)。它是 _.keysIn 方法的基础实现之一,通过原生的 for...in 循环遍历对象的所有可枚举属性,包括从原型链继承的属性。

nativeKeys(基于 Object.keys 实现)不同,nativeKeysIn 采用了更简单直接的方式,直接利用 JavaScript 的 for...in 循环来获取对象的所有可枚举属性,无论是自身的还是继承的。

前置学习

依赖函数

虽然 nativeKeysIn 本身没有直接依赖其他函数,但理解以下函数有助于更全面地理解它在 Lodash 中的定位:

  • baseKeysIn:获取对象所有可枚举属性名的基础实现,会根据对象类型调用 nativeKeysIn
  • keysIn:对外暴露的 API,用于获取对象自身和继承的可枚举属性名

内部调用链:keysInbaseKeysInnativeKeysIn

技术知识

  • for...in 循环:JavaScript 中用于遍历对象所有可枚举属性(包括继承属性)的循环结构
  • 可枚举属性 :JavaScript 对象属性的一个特性,决定属性是否会出现在 for...in 循环中
  • 原型链:JavaScript 对象继承机制的基础,理解原型链对于理解属性继承至关重要
  • Object 构造函数:用于将原始值转换为对象,确保安全地访问属性

源码实现

javascript 复制代码
function nativeKeysIn(object) {
  var result = [];
  if (object != null) {
    for (var key in Object(object)) {
      result.push(key);
    }
  }
  return result;
}

实现思路

nativeKeysIn 函数的实现思路非常直接:

  1. 创建一个空数组,用于存储属性名
  2. 判断输入对象是否为 null 或 undefined,如果是则直接返回空数组
  3. 使用 for...in 循环遍历对象的所有可枚举属性(包括继承的)
  4. 将每个属性名添加到结果数组中
  5. 返回最终的属性名数组

这种实现方式利用了 JavaScript 的 for...in 循环特性,该循环会遍历对象自身的可枚举属性以及从原型链继承的可枚举属性,完美符合 keysIn 方法的需求。

源码解析

让我们逐行分析 nativeKeysIn 函数的实现:

函数签名和结果初始化

javascript 复制代码
function nativeKeysIn(object) {
  var result = [];
  • 函数接收一个参数 object,可以是任何类型的值
  • 创建一个空数组 result,用于存储属性名

空值处理

javascript 复制代码
if (object != null) {
  • 使用宽松比较 != 检查 object 是否为 nullundefined
  • 这是一种安全防护措施,确保不会在 nullundefined 上调用 for...in 循环

属性遍历和收集

javascript 复制代码
for (var key in Object(object)) {
  result.push(key);
}
  • Object(object) 将输入转换为对象类型,这是一种防御性编程的做法:
    • 如果 object 已经是对象,保持不变
    • 如果 object 是原始类型(如字符串、数字、布尔值),将其包装为对应的对象类型
    • 如果 objectnullundefined(虽然已经在前面检查过),则返回空对象 {}
  • for...in 循环遍历对象的所有可枚举属性,包括自身的和继承的
  • 每个属性名通过 push 方法添加到 result 数组中

返回结果

javascript 复制代码
  }
  return result;
}
  • 返回包含所有收集到的属性名的数组

应用场景

nativeKeysIn 函数主要通过 baseKeysInkeysIn 函数被应用,适用于需要考虑继承属性的场景:

1. 获取对象所有属性(包括继承的)

javascript 复制代码
function Foo() {
  this.a = 1;
  this.b = 2;
}
Foo.prototype.c = 3;

const foo = new Foo();
console.log(_.keysIn(foo)); // ['a', 'b', 'c']

内部调用链:keysInbaseKeysInnativeKeysIn

注意事项

使用 nativeKeysIn(通过 keysIn)时需要注意以下几点:

  1. 性能考虑:遍历所有继承属性可能会比仅遍历自身属性慢,特别是对于原型链较长的对象

  2. 非可枚举属性nativeKeysIn 只返回可枚举属性,非可枚举属性不会被收集

  3. 符号属性 :Symbol 类型的属性会被忽略,因为 for...in 循环不会遍历 Symbol 属性

  4. 属性排序:不同 JavaScript 引擎可能会以不同顺序遍历属性,不要依赖属性的顺序

  5. 原型污染 :如果原型链被恶意修改(原型污染),nativeKeysIn 可能会返回意外的属性

与 baseKeys 和 nativeKeys 的比较

为了更好地理解 nativeKeysIn,让我们将它与相关函数进行比较:

函数 获取自身属性 获取继承属性 实现方式 使用场景
nativeKeys 包装 Object.keys 仅需要获取自身属性的场景
baseKeys 使用 nativeKeys 或手动实现 处理普通对象和原型对象
nativeKeysIn 使用 for...in 循环 需要获取所有属性的场景
baseKeysIn 使用 nativeKeysIn 或手动实现 处理不同类型的对象

总结

nativeKeysIn 函数是 Lodash 中的一个简单而强大的工具函数,用于获取对象的所有可枚举属性名,包括从原型链继承的属性。它的主要特点包括:

  1. 简单性 :直接利用 JavaScript 的 for...in 循环,实现简洁明了
  2. 完整性:返回对象的所有可枚举属性,包括继承的属性
  3. 安全性 :通过 Object() 和 null 检查,确保处理各种输入类型
  4. 实用性:在需要处理继承属性的场景中非常有用,如对象合并、深度克隆等
相关推荐
一拳不是超人11 分钟前
DeepSeek Harness 为什么敢说"一切皆插件"?拆透 Cordis 引擎的五大核心机制
前端·人工智能·agent
IT_陈寒23 分钟前
Python的GIL让我多写了500行代码
前端·人工智能·后端
风骏时光牛马24 分钟前
AI智能体能力调度微服务
前端
Eloudy2 小时前
ReAct 原理简介
前端·javascript·人工智能·react.js·agent·gpu
ZJU_统一阿萨姆3 小时前
【DSH】如何将 DeepSeek Harness 嵌入生产环境?万字解构 DeepSeek Agent Harness 的运行机制与安全边界
前端·javascript·安全
用户921080262863 小时前
4. 前端地图大量点位实时更新优化:后端推增量,前端做 diff
前端
SoaringHeart3 小时前
Flutter最佳实践:Web项目中文字体首次加载乱码问题解决
前端·flutter
西安小哥4 小时前
破局与重生:大厂前端如何借力 AI 转型“超级全栈“
前端·人工智能
sunly_5 小时前
TypeScript总结:16、面向对象速查
前端·javascript·typescript
张元清5 小时前
React useInterval Hook:没有过期闭包的 setInterval (2026)
javascript·react.js