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. 实用性:在需要处理继承属性的场景中非常有用,如对象合并、深度克隆等
相关推荐
艾恩小灰灰13 分钟前
CSS中的`transform-style`属性:3D变换的秘密武器
前端·css·3d·css3·html5·web开发·transform-style
Captaincc14 分钟前
AI coding的隐藏王者,悄悄融了2亿美金
前端·后端·ai编程
天天扭码18 分钟前
一分钟解决一道算法题——矩阵置零
前端·算法·面试
抹茶san30 分钟前
el-tabs频繁切换tab引发的数据渲染混淆
前端·vue.js·element
巴巴_羊31 分钟前
JavsScript 原型链
开发语言·javascript·原型模式
Captaincc34 分钟前
关于MCP最值得看的一篇:MCP创造者聊MCP的起源、架构优势和未来
前端·mcp
小小小小宇38 分钟前
记录老项目Vue 2使用VueUse
前端
vvilkim38 分钟前
React Server Components 深度解析:下一代 React 渲染模式
前端·react.js·前端框架
HBR666_1 小时前
vue3 excel文件导入
前端·excel
天天扭码1 小时前
偶遇天才算法题 | 拼劲全力,无法战胜 😓
前端·算法·面试