前端开发中的常用工具函数(九)

二十三、at() 方法:通过索引(支持负数倒数)获取数组或字符串中的元素

在前端日常开发中,我们经常需要获取数组或字符串中的特定元素。如果是要获取最后一个元素,传统写法总是离不开 arr[arr.length - 1] 或者 arr.slice(-1)[0]。这种写法不仅冗长,而且可读性一般。

为了解决这个痛点,ES2022 引入了一个非常实用的函数工具:at() 方法。

1. 基本语法

at() 方法接收一个整数值作为参数,返回该索引对应的数组或字符串元素。它最大的亮点在于支持负数索引

语法结构:

javascript 复制代码
// 数组
Array.prototype.at(index)
// 字符串
String.prototype.at(index)
// TypedArray
TypedArray.prototype.at(index)

参数说明:

  • index(可选):要返回的元素的索引(从零开始)。如果传入负数,则会从数组/字符串的末尾开始倒数。即 -1 代表最后一个元素,-2 代表倒数第二个元素,依此类推。

返回值:

  • 返回指定索引处的元素。如果索引超出范围(找不到对应元素),则返回 undefined

2. 基础示例

我们通过几个简单的例子来快速了解它的用法。

1. 数组的基础使用

javascript 复制代码
const cart = ['苹果', '香蕉', '橙子', '葡萄'];

// 正向索引(和传统写法一致)
console.log(cart.at(0)); // '苹果'

// 负向索引(核心特性!)
console.log(cart.at(-1)); // '葡萄' (相当于 cart[cart.length - 1])
console.log(cart.at(-2)); // '橙子'

// 越界访问
console.log(cart.at(10)); // undefined (不会报错,非常优雅)

2. 字符串的基础使用

javascript 复制代码
const filename = "app.component.ts";

console.log(filename.at(0)); // 'a'
console.log(filename.at(-1)); // 's'

// 结合 trim() 等链式调用
const greeting = "   Hello World   ";
console.log(greeting.trim().at(-1)); // 'd'

3. 企业开发中的实际应用场景

在企业级前端开发中,at() 方法不仅能让代码更简洁,还能在特定业务逻辑下大放异彩。

场景一:面包屑导航与路由历史记录

在后台管理系统中,我们经常需要处理路由历史。比如获取用户上一次访问的页面,或者在面包屑导航中获取当前层级的上一级页面。

javascript 复制代码
const routeHistory = ['/', '/dashboard', '/dashboard/user', '/dashboard/user/profile'];

// 传统写法
const prevRoute = routeHistory[routeHistory.length - 2]; 

// 使用 at() 更加语义化
const currentRoute = routeHistory.at(-1); // '/dashboard/user/profile'
const parentRoute = routeHistory.at(-2);  // '/dashboard/user'

场景二:富文本编辑器/画板撤销操作(栈操作)

在实现类似 Figma 画板或富文本编辑器时,操作历史通常存在一个数组中。撤销操作就是弹出栈顶元素。

javascript 复制代码
const actionStack = ['createRect', 'changeColor', 'moveRect', 'resizeRect'];

function undo() {
    if (actionStack.length === 0) return;
    const lastAction = actionStack.at(-1); // 查看最后一个操作
    console.log(`正在撤销操作: ${lastAction}`);
    actionStack.pop(); // 真正移除
}

场景三:解析文件后缀名

在处理文件上传时,经常需要提取文件后缀。虽然可以用 lastIndexOf,但配合 splitat 写起来非常清爽。

javascript 复制代码
function getFileExtension(filename) {
    // 将文件名按 '.' 分割,取最后一部分
    return filename.split('.').at(-1);
}

console.log(getFileExtension("avatar.png"));      // 'png'
console.log(getFileExtension("app.config.json"));  // 'json'
console.log(getFileExtension("no_extension_file")); // 'no_extension_file' (注意这种边界情况)

场景四:UI 组件轮播图无缝滚动

在实现无限轮播图时,有时需要把最后一张图克隆到第一张图前面,或者获取最后一张图做平滑过渡。

javascript 复制代码
const slides = document.querySelectorAll('.slide-item');
const slidesArray = Array.from(slides);

// 获取最后一张幻灯片节点进行克隆
const lastSlideClone = slidesArray.at(-1).cloneNode(true);
// 插入到第一张前面
slidesContainer.insertBefore(lastSlideClone, slidesArray[0]);

4. 注意事项

虽然 at() 方法非常好用,但在引入项目之前,需要注意以下几点:

(1) 浏览器兼容性

at() 方法是 ES2022 引入的相对较新的特性。在现代浏览器(Chrome 92+, Firefox 90+, Safari 15.4+)中支持良好。但如果你的项目需要兼容老旧浏览器(如 IE 或低版本 Safari),则不能直接使用,需要通过 Babel 进行 polyfill,或者谨慎使用。

(2) 小数会被截断(向下取整)

如果你不小心传入了小数,at() 不会报错,而是会将其进行向下取整处理。

javascript 复制代码
const arr = [10, 20, 30, 40];
console.log(arr.at(1.9)); // 20 (等同于 arr.at(1))
console.log(arr.at(-1.9)); // 30 (等同于 arr.at(-2),注意负数也是向负无穷取整)

(3) 仅支持整数,不支持布尔值等隐式转换

在传统的方括号语法 arr[] 中,JS 会发生隐式类型转换,但 at() 方法则严格得多。如果传入非数字,它会尝试转换为整数,但强烈建议只传整数。

javascript 复制代码
const arr = [1, 2, 3];
arr['1'] // 2 (隐式转换)
arr.at('1') // 2 (内部会做 ToInteger 转换,但不推荐这样写,代码可读性差)

(4) 与 Lodash 的 _.at 区别

如果你项目中使用了 Lodash,请注意区分:

  • 原生 at():只接收一个索引参数,返回单个元素。
  • Lodash _.at():接收多个索引,返回一个包含这些索引对应元素的新数组。
javascript 复制代码
const arr = ['a', 'b', 'c', 'd'];

// Lodash
_.at(arr, [1, 3]); // ['b', 'd']

// 原生 at
arr.at(1); // 'b'

(5) 性能考量

在极高频的循环操作中(如百万次级别的数组末端访问),原生方括号语法 arr[arr.length - 1] 的执行速度理论上会略快于 arr.at(-1),因为后者涉及一次函数调用的开销。但在 99% 的日常前端业务中,这点性能差异可以忽略不计。为了代码的可读性和可维护性,推荐优先使用 at()

相关推荐
蓝创工坊Blue Foundry1 小时前
图片文字提取到 Excel:批量任务如何先定义要交付的字段
运维·服务器·开发语言·数据库·自动化·ocr·excel
会飞的小新1 小时前
C 标准库之 <fenv.h> 详解与深度解析
c语言·开发语言·microsoft
大不点wow2 小时前
Java序列化与反序列化:让对象走出JVM
java·开发语言·jvm
阿里嘎多学长2 小时前
2026-07-22 GitHub 热点项目精选
开发语言·程序员·github·代码托管
噢,我明白了2 小时前
Java中日期和字符串的处理
java·开发语言·日期
爱刷碗的苏泓舒2 小时前
C 语言 if-else 与 switch-case 分支语句对比
c语言·开发语言
-银雾鸢尾-2 小时前
C#中的泛型约束
开发语言·c#
Revolution612 小时前
一段 JavaScript 代码执行时,到底发生了什么
前端·javascript
雪碧透心凉_3 小时前
while 循环与循环嵌套
开发语言·python