news 2026/9/15 13:35:48

es-toolkit/compat nth() 详解:兼容 Lodash 的按索引取数组元素函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
es-toolkit/compat nth() 详解:兼容 Lodash 的按索引取数组元素函数

es-toolkit/compat nth() 详解:兼容 Lodash 的按索引取数组元素函数

【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit

导读

nth()是 es-toolkit 兼容层(es-toolkit/compat)中用于按索引获取数组元素的函数,它 1:1 复刻了 Lodash_.nth的行为,支持负索引从数组末尾计数,并针对越界、null/undefined输入等边界情况做了统一处理。本文将以 docs/compat/reference/array/nth.md 为核心,结合 nth 源码 与其单元测试,完整讲解nth()的签名、参数、返回值、边界行为以及底层实现原理,并给出在实际项目中的使用与迁移建议。

背景:为什么需要nth以及何时不该用它

nth属于es-toolkit/compat兼容层。正如 compat 介绍文档 所述,es-toolkit/compat镜像了 Lodash 的接口与行为,其存在的意义是让已有 Lodash 代码库无需改写调用点即可平滑迁移到 es-toolkit,之后再逐步切换到严格类型的es-toolkit主包。

因此,nth的典型使用场景是旧代码迁移期——当代码中原本写的是_.nth(array, index),你可以把导入路径从lodash直接换成es-toolkit/compat,行为保持一致。

需要特别注意的是,官方文档在函数开头就给出了明确的警告(::: warning):

优先使用数组索引访问由于需要处理null/undefined输入以及整数转换,nth函数的运行速度较慢。 请改用更快、更现代的数组索引访问方式(array[index]array.at(index))。

也就是说,如果你的项目没有历史包袱、并不是在迁移 Lodash 代码,那么直接使用原生语法array[index]array.at(index)即可——nth的存在意义是行为兼容,而不是性能最优。这也是 es-toolkit 设计哲学的一部分:兼容层为了对齐 Lodash 的隐式类型转换等行为,会携带额外逻辑,因此“略大、略慢”(详见 docs/compat/intro.md 中 “How it differs fromes-toolkit” 一节)。

函数签名与类型定义

nth的 TypeScript 签名如下:

const element = nth(array, index);

对应源码中的实际定义(src/compat/array/nth.ts):

export function nth<T>(array: ArrayLike<T> | null | undefined, n = 0): T | undefined

参数说明

参数类型是否可选说明
arrayArrayLike<T> \| null \| undefined必填要查询的数组(或类数组对象)
indexnumber可选要获取元素的索引。为负数时从数组末尾计数。默认值为0

返回值

T | undefined:返回指定索引处的元素;如果索引越界,返回undefined

值得留意的是默认值:index省略时相当于nth(array, 0),即返回数组第一个元素,这与 Lodash_.nth的默认行为一致。

使用方式与代码示例

es-toolkit/compat导入

import { nth } from 'es-toolkit/compat'; const array = [1, 2, 3<|begin▁of▁sentence|> , 4, 5]; // 正索引 nth(array, 1); // => 2 // 负索引(从末尾计数) nth(array, -1); // => 5 nth(array, -2); // => 4 // 越界索引 nth(array, 10); // => undefined nth(array, -10); // => undefined

nullundefined的输入

nullundefined会被当作undefined处理:

import { nth } from 'es-toolkit/compat'; nth(null, 0); // undefined nth(undefined, 0); // undefined

按需导入(独立入口)

lodash/merge的形态类似,compat 层的每个函数都拥有独立入口,只加载该函数所需的文件,而不是整个es-toolkit/compat模块。这在无法进行 tree-shaking 的环境(如 CommonJSrequire()、React Native、无打包器直接在 Node.js 上运行)中尤其有用(参考 docs/compat/intro.md 的 “Importing individual functions” 一节):

import nth from 'es-toolkit/compat/nth';

或 CommonJS 风格:

const nth = require('es-toolkit/compat/nth');

源码实现与底层原理

完整的实现非常精简(src/compat/array/nth.ts 全文 27 行):

export function nth<T>(array: ArrayLike<T> | null | undefined, n = 0): T | undefined { if (!isArrayLike(array) || array.length === 0) { return undefined; } n = toInteger(n); if (n < 0) { n += array.length; } return array[n]; }

下面逐行拆解其内部逻辑,并结合测试用例印证每一步行为。

第一步:isArrayLike校验与空数组短路

if (!isArrayLike(array) || array.length === 0) { return undefined; }

isArrayLike的实现位于 src/compat/predicate/isArrayLike.ts:

export function isArrayLike(value?: any): boolean { return value != null && typeof value !== 'function' && isLength((value as ArrayLike<unknown>).length); }

它要求三个条件同时成立:

  1. value != null:排除nullundefined
  2. typeof value !== 'function':函数永远不被视为类数组;
  3. value.length是一个合法的“长度值”(isLength,即非负有限整数)。

这意味着:

  • nth(null, 0)nth(undefined, 0)返回undefined(对应文档示例与测试中的 “should returnundefinedfor empty arrays” 用例);
  • 空数组[]直接返回undefined,无需再做索引计算;
  • 字符串也是合法的类数组,因此nth('abc', 0) === 'a'nth('abc', -1) === 'c'(测试用例 “should support strings” 验证了这一点)。

第二步:toInteger索引整数化

n = toInteger(n);

toInteger的实现位于 src/compat/util/toInteger.ts:

export function toInteger(value: any): number { const finite = toFinite(value); const remainder = finite % 1; return remainder ? finite - remainder : finite; }

其行为链是toInteger → toFinite → toNumber

  • 小数会被向下取整:nth(array, 1.6)等效于nth(array, 1)(测试用例 “should coercento an integer” 验证了1.6 → 'b'即索引 1 的结果);
  • 字符串数字会被转换:nth(array, '1')等效于nth(array, 1)
  • falseNaN、空字符串等 falsy 值会被转为0,即退化为取第一个元素;
  • Infinity会经toFinite收敛为Number.MAX_VALUE,这必然越界,从而返回undefined(测试用例 “should returnundefinedfor non-indexes” 验证了Infinityarray.length都返回undefined)。

第三步:负索引从末尾计数

if (n < 0) { n += array.length; }

当索引为负时,将其加上数组长度转换为正向索引。例如nth([1, 2, 3, 4, 5], -1)n = -1 + 5 = 4,取到array[4] === 5。测试用例 “should work with a negativen” 使用range(1, array.length + 1)['a','b','c','d']逐次取-1-4,验证结果为['d', 'c', 'b', 'a']

注意:如果负索引的绝对值超过数组长度,比如nth(array, -10),则n = -10 + 5 = -5array[-5]在 JavaScript 中读取到的是对象上的-5属性(不存在),因此返回undefined——这正是文档中“越界返回undefined”的体现。

第四步:返回元素

return array[n];

最终通过索引直接读取返回。整个过程没有做任何额外的“是否存在该索引”的显式判断,而是依赖 JavaScript 数组越界访问天然返回undefined的特性。

边界行为一览(附测试佐证)

结合 src/compat/array/nth.spec.ts 中的全部用例,可将nth的边界行为总结如下:

输入行为测试用例
nth(array, index)(正索引)返回对应元素should get the nth element ofarray
nth(array, -n)(负索引)从末尾计数返回元素should work with a negativen
nth(array, 1.6)/nth(array, '1')索引被整数化 / 字符串化转换should coercento an integer
nth(null, n)/nth(undefined, n)/nth([], n)返回undefinedshould returnundefinedfor empty arrays
nth('abc', n)支持字符串类数组should support strings
nth(array, Infinity)/nth(array, array.length)返回undefined(越界)should returnundefinedfor non-indexes

其中 “should returnundefinedfor non-indexes” 这个用例还揭示了一个细节:测试特意给数组设置了array[-1] = 3(在数组对象上挂一个-1属性),然后调用nth(array, -1)之外的越界场景,验证nth不会误读这类非索引属性——因为负数索引经过n += array.length之后已经不再是负数,自然不会命中array[-1]这样的属性键。这说明nth的负索引处理是严格基于“真实数组位置”而非属性查找的。

性能注意点与迁移建议

  1. 新代码请直接用array.at(index)at是 ES2022 引入的原生方法,同样支持负索引(array.at(-1)即最后一个元素),且没有任何类型转换开销。nth的额外成本主要来自isArrayLike校验和toInteger整数转换——文档明确提示这一点。
  2. 迁移 Lodash 旧代码时:把import { nth } from 'lodash'改为import { nth } from 'es-toolkit/compat',调用点无需改动,行为完全一致;后续可再逐步清理为原生at/索引访问。
  3. 追求极致体积时:使用按需入口es-toolkit/compat/nth或依赖打包器的 tree-shaking,只打包该函数及其依赖(isArrayLiketoIntegertoFinitetoNumberisLength)。

小结

nth是 es-toolkit 兼容层中一个“小而精”的函数:27 行源码,通过isArrayLike空值守卫、toInteger索引规范化、负索引长度换算三步,完整复刻了 Lodash_.nth的语义,包括空输入返回undefined、字符串类数组支持、小数与字符串索引的隐式转换等细节,并有覆盖全面的单元测试作为行为契约。理解它的实现,既能让你在迁移 Lodash 代码时放心替换,也能帮你更清晰地认识到何时应该放弃它、改用原生array[index]array.at(index)

【免费下载链接】es-toolkitA modern JavaScript utility library that's 2-3 times faster and up to 97% smaller, a major upgrade to lodash.项目地址: https://gitcode.com/GitHub_Trending/es/es-toolkit

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 13:30:52

text-to-cad URDF验证工具解析:一次通过8类机器人模型检查

text-to-cad URDF验证工具解析&#xff1a;一次通过8类机器人模型检查 【免费下载链接】text-to-cad A library of agent skills for CAD, CAE and CAM 项目地址: https://gitcode.com/GitHub_Trending/tex/text-to-cad text-to-cad 是一个面向 AI 智能体的 CAD/CAE/CAM…

作者头像 李华
网站建设 2026/9/15 13:30:42

网页版贪吃蛇游戏开发:Canvas、游戏循环与移动端适配实战

简介&#xff1a;这份网页版贪吃蛇游戏源码包以纯前端技术实现&#xff0c;适合前端初学者、游戏开发爱好者作为练手项目&#xff0c;也适合讲师在课堂上演示游戏循环、键盘事件处理与界面更新流程。无需服务器环境&#xff0c;解压后直接在浏览器打开即可体验&#xff0c;完整…

作者头像 李华
网站建设 2026/9/15 13:29:37

前端开发建站出海:从接单到稳定收入的全流程指南

去年有个前端的同行跟我抱怨&#xff0c;给国内客户做一个公司官网&#xff0c;报价从 3000 块谈到 800 块&#xff0c;最后还被一句“顺便把小程序也做了”差点搞崩溃。同一个月&#xff0c;我在海外市场接了一个 10 页左右的建站项目&#xff0c;报价 2500 美元&#xff0c;客…

作者头像 李华
网站建设 2026/9/15 13:28:12

DiceDB `COMMAND INFO` 命令详解:元数据查询与底层实现剖析

DiceDB COMMAND INFO 命令详解&#xff1a;元数据查询与底层实现剖析 【免费下载链接】dicedb Open-source, low-latency key/value engine built on Valkey with query subscriptions and hierarchical storage tiers. 项目地址: https://gitcode.com/GitHub_Trending/dic/d…

作者头像 李华
网站建设 2026/9/15 13:25:32

NVIDIA与Hugging Face协同部署实战:打通AI模型GPU运行最后一公里

1. 项目概述&#xff1a;这不是一次普通收购&#xff0c;而是一场AI基础设施层的定向整合最近刷到“NVIDIA以129.3亿美元收购Hugging Face”这个标题&#xff0c;不少朋友第一反应是——等等&#xff0c;这新闻我怎么没在官网看到&#xff1f;翻遍NVIDIA官网新闻稿、SEC文件、H…

作者头像 李华