在 JavaScript 中,数组取值是最基础也最频繁的操作之一。我们习惯了用 示例:获取数组末尾元素 可以看到, 示例:各种索引情况的返回值 传统方式获取倒数第 示例:动态获取倒数元素 示例:处理动态索引 示例:数组与字符串的 at () 对比 对于同时操作数组和字符串的场景,这种一致性会让代码更统一、易维护。 在处理列表、队列等数据结构时,获取最后一个元素是高频操作。 当索引值来自用户输入或动态计算时, 栈(Stack)的 当索引可能超出数组范围时, 若需要精确处理非整数索引(如分页计算中的浮点数),需先手动转换为整数。 对于稀疏数组(存在未定义元素的数组), 这个 polyfill 完美模拟了 在实际开发中, 下次需要获取数组的倒数第arr[0]
获取第一个元素,用arr[arr.length - 1]
获取最后一个元素。但当需要访问倒数第二个、第三个元素时,arr[arr.length - 2]
这样的写法不仅繁琐,还容易出错。ES2022 引入的Array.prototype.at()
方法,就像给数组配备了一把 “精准定位的钥匙”,让我们能更简洁、直观地访问任意位置的元素,尤其是负数索引对应的倒数元素。今天,我们就来解锁这个提升数组操作体验的新方法。一、认识 at ():数组索引的 “语法糖”
at()
是数组原型上的实例方法,用于根据索引值获取数组元素。它的核心特点是支持负数索引—— 当传入负数时,会从数组末尾开始计数(如-1
表示最后一个元素,-2
表示倒数第二个元素),完美解决了传统索引写法的痛点。1.1 与传统索引取值的对比
arr[0]
arr.at(0)
arr[arr.length - 1]
arr.at(-1)
at()
arr[arr.length - 2]
arr.at(-2)
at()
arr.length
,减少出错概率arr[index]
index
非负)arr.at(index)
at()
const fruits = ["苹果", "香蕉", "橙子", "葡萄"];
// 传统方式:获取最后一个元素
const lastFruitOld = fruits[fruits.length - 1];
console.log(lastFruitOld); // '葡萄'
// at()方式:获取最后一个元
const lastFruitNew = fruits.at(-1);
console.log(lastFruitNew); // '葡萄'
// 获取倒数第二个元素
const secondLastOld = fruits[fruits.length - 2];
const secondLastNew = fruits.at(-2);
console.log(secondLastOld, secondLastNew); // '橙子' '橙子'at(-1)
比fruits.length - 1
更简洁,且意图更明确 —— 直接表明 “取最后一个元素”。1.2 基础语法:简单直观的调用方式
at()
的语法非常简单,仅接收一个参数(索引值):array.at(index);
index
:可选,整数类型,用于指定要访问的元素位置。0
表示第一个元素,1
表示第二个元素,以此类推)。-1
表示最后一个元素,-2
表示倒数第二个元素,以此类推)。index
省略,默认值为0
,即返回第一个元素。undefined
。const numbers = [10, 20, 30, 40];
console.log(numbers.at(0)); // 10(第一个元素)
console.log(numbers.at(2)); // 30(第三个元素)
console.log(numbers.at(-1)); // 40(最后一个元素)
console.log(numbers.at(-3)); // 20(倒数第三个元素)
console.log(numbers.at(10)); // undefined(索引超出范围)
console.log(numbers.at(-5)); // undefined(负索引超出范围)
console.log(numbers.at()); // 10(省略索引,默认取0)二、核心优势:为什么要用 at ()?
at()
并非凭空新增的复杂功能,而是对传统索引取值的优化,其优势主要体现在以下几个方面:2.1 简化负数索引操作,减少代码冗余
n
个元素时,必须写arr[arr.length - n]
,不仅繁琐,还可能因重复书写arr.length
导致笔误(如少写一个-
号)。at(-n)
直接对应 “倒数第n
个”,语义清晰,代码更短。// 传统方式:获取倒数第k个元素
function getLastKthOld(arr, k) {
return arr[arr.length - k];
}
// at()方式:获取倒数第k个元素
function getLastKthNew(arr, k) {
return arr.at(-k);
}
const list = ["a", "b", "c", "d"];
console.log(getLastKthOld(list, 2)); // 'c'
console.log(getLastKthNew(list, 2)); // 'c'getLastKthNew
的实现更简洁,且-k
的意图比arr.length - k
更直观。2.2 兼容正负索引,提升代码灵活性
at()
统一了正数索引和负数索引的取值方式,无需根据索引正负编写不同逻辑。对于动态传入的索引(如函数参数),at()
能自动适配,避免额外的条件判断。// 传统方式:需判断索引正负
function getElementOld(arr, index) {
if (index >= 0) {
return arr[index];
} else {
return arr[arr.length + index]; // 负数索引转换为正数
}
}
// at()方式:无需判断,直接支持正负索引
function getElementNew(arr, index) {
return arr.at(index);
}
const data = [1, 2, 3, 4];
console.log(getElementOld(data, 2)); // 3
console.log(getElementOld(data, -2)); // 3
console.log(getElementNew(data, 2)); // 3
console.log(getElementNew(data, -2)); // 3getElementNew
无需额外处理负数索引,代码更简洁,且减少了出错风险。2.3 与字符串方法保持一致,降低学习成本
String.prototype.at``()
与Array.prototype.at``()
的用法完全一致(都支持正负索引),掌握一个即可触类旁通。这种 API 设计的一致性,能降低开发者的学习和记忆成本。// 数组
const arr = ["x", "y", "z"];
console.log(arr.at(-1)); // 'z'
// 字符串
const str = "xyz";
console.log(str.at(-1)); // 'z'三、实战场景:at () 的实用案例
at()
在日常开发中能简化多种数组操作场景,尤其是需要访问末尾元素的情况。3.1 获取数组最后一个元素(最常见场景)
at(-1)
比arr[arr.length - 1]
更简洁,且在链式调用中更优雅。// 处理API返回的列表数据,获取最新一条记录
const apiData = await fetch("/api/logs").then((res) => res.json());
const latestLog = apiData.logs.at(-1); // 无需写 apiData.logs[apiData.logs.length - 1]
// 链式调用中使用
const lastEvenNumber = [1, 3, 5, 2, 4].filter((n) => n % 2 === 0).at(-1);
console.log(lastEvenNumber); // 4(过滤后数组的最后一个元素)3.2 处理用户输入的索引值
at()
能自动处理正负值,无需额外转换。// 假设index来自用户输入(可能为正或负)
const userInputIndex = -2;
const items = ["item1", "item2", "item3", "item4"];
// 直接使用at(),无需判断正负
const selectedItem = items.at(userInputIndex);
console.log(selectedItem); // 'item3'(倒数第二个元素)3.3 实现数组的 “栈” 操作
pop
方法用于移除并返回最后一个元素,若只想 “查看” 最后一个元素而不移除,at(-1)
是最佳选择。class Stack {
constructor() {
this.data = [];
}
push(item) {
this.data.push(item);
}
// 查看栈顶元素(最后一个元素)
peek() {
return this.data.at(-1); // 比 this.data[this.data.length - 1] 更简洁
}
// 移除并返回栈顶元素
pop() {
return this.data.pop();
}
}
const stack = new Stack();
stack.push("a");
stack.push("b");
console.log(stack.peek()); // 'b'(查看栈顶)
console.log(stack.pop()); // 'b'(移除栈顶)
console.log(stack.peek()); // 'a'3.4 安全处理超出范围的索引
at()
与传统索引一样返回undefined
,但写法更简洁。const colors = ["红", "绿", "蓝"];
// 传统方式:索引超出范围返回undefined
console.log(colors[10]); // undefined
// at()方式:同样返回undefined,写法更短
console.log(colors.at(10)); // undefined
console.log(colors.at(-5)); // undefined四、避坑指南:使用 at () 的注意事项
4.1 索引必须是整数,非整数会被截断
at()
会将非整数索引自动截断为整数(即忽略小数部分),这与传统索引的行为一致,但需注意避免传入非预期的小数。const nums = [10, 20, 30];
console.log(nums.at(1.9)); // 20(等同于1)
console.log(nums.at(-2.3)); // 20(等同于-2)
console.log(nums.at(NaN)); // 10(NaN等同于0)4.2 与稀疏数组的交互
at()
会返回指定索引处的实际值(包括undefined
),与传统索引一致。const sparseArr = [1, , 3]; // 稀疏数组,索引1处未定义
console.log(sparseArr.at(1)); // undefined
console.log(sparseArr[1]); // undefined(行为一致)4.3 浏览器兼容性与降级方案
at()
是 ES2022 的新增方法,兼容所有现代浏览器(Chrome 92+、Firefox 90+、Safari 15.4+、Edge 92+),但 IE 完全不支持。如需兼容旧浏览器,可使用以下降级方案:// 为不支持at()的环境添加polyfill
if (!Array.prototype.at) {
Array.prototype.at = function (index) {
// 处理索引:默认0,支持负数
index = Math.trunc(index) || 0;
if (index < 0) index += this.length;
// 检查索引范围
if (index < 0 || index >= this.length) returnundefined;
// 返回对应元素
return this[index];
};
}at()
的行为,可在旧环境中安全使用。4.4 不要过度使用:简单场景无需替换传统索引
at()
的优势在负数索引场景中最明显,对于正数索引(如arr.at``(0)
),与arr[0]
相比并无优势,反而可能让习惯传统写法的开发者感到陌生。因此,建议:0
、1
等小索引)时,继续使用arr[index]
。at()
。五、总结
Array.prototype.at``()
作为数组取值的新方式,虽然功能简单,却带来了显著的体验提升:at(-1)
替代arr[arr.length - 1]
,减少代码冗余,提升可读性。at()
方法用法一致,且兼容传统索引的思维模式。at()
尤其适合处理需要访问数组末尾元素的场景(如获取最新数据、栈操作、倒数元素取值等)。它不是要取代传统的[]
索引,而是作为一种补充,让我们在合适的场景中写出更优雅的代码。n
个元素时,不妨试试at(-n)
—— 这个小小的语法优化,可能会让你的代码更简洁、更易维护。

优网科技秉承"专业团队、品质服务" 的经营理念,诚信务实的服务了近万家客户,成为众多世界500强、集团和上市公司的长期合作伙伴!
优网科技成立于2001年,擅长网站建设、网站与各类业务系统深度整合,致力于提供完善的企业互联网解决方案。优网科技提供PC端网站建设(品牌展示型、官方门户型、营销商务型、电子商务型、信息门户型、微信小程序定制开发、移动端应用(手机站、APP开发)、微信定制开发(微信官网、微信商城、企业微信)等一系列互联网应用服务。