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. 实用性:在需要处理继承属性的场景中非常有用,如对象合并、深度克隆等
相关推荐
程序猿阿伟2 分钟前
《从点击到共鸣:论坛前端如何用交互细节编织用户体验》
前端·ux
樱花开了几轉2 分钟前
React中的合成事件解释和理解
前端·javascript·react.js
code_life6 分钟前
动态格式化时间
javascript
Hizuna8 分钟前
问题探索:某些场景下H5页面能够触发,而uniapp微信小程序不能触发
前端
一个很帅的帅哥18 分钟前
Webpack 和 Vite 的关键区别
前端·webpack·前端框架·node.js
小高00728 分钟前
告别“if-else”条件判断:5 个让 JavaScript 逻辑更优雅的写法
前端·javascript
二闹36 分钟前
前端安全:你还在忽视这3个致命 XSS 漏洞?
前端
前端的日常39 分钟前
面试必备:前端路由 route 和 router 的核心要点
前端
icr1 小时前
React Fiber和React:diff 算法
前端
妮妮喔妮1 小时前
重构vite.config.json
javascript·重构·json