at():取倒数第几个,别再 length-1 了
用 Array.prototype.at(-1) 取倒数元素,别再手写 length-1,更别指望 arr[-1];只读访问,写回配合 with()。
要解决的问题
前端里取「最后一个」「倒数第二个」元素太常见了:历史栈顶、分页最后一项、消息列表最新一条。很多人习惯写 arr[arr.length - 1],或者以为像 Python 一样能写 arr[-1]。
后者在 JavaScript 里根本不管用:方括号里的 -1 会被当成字符串属性名 "-1",读到的是普通对象属性,不是数组下标。前者能用,但每次都手算 length,可读性差,还容易写成 length - 2 时漏减、多减。
标准库 Array.prototype.at()(以及字符串的 String.prototype.at())就是干这事的:传入整数下标,负数从末尾往回数。按 MDN,这是 Baseline 广泛可用特性,各主流浏览器自 2022 年 3 月起都已支持(Chrome/Edge 92+、Firefox 90+、Safari 15.4+)。本文示例已在本机 Node.js v20.19.2 跑通。
核心概念
记住这几条(以 MDN 为准):
- 语法:
arr.at(index)。index会转成整数;index >= 0时与arr[index]等价;index < 0时访问index + arr.length。 - 越界:
index < -arr.length或index >= arr.length时直接返回undefined,不会去读奇怪的属性。 - 只读:
at()只负责取值。不能用它给负数下标赋值;若要用相对下标写回,MDN 建议配合with()(返回新数组,不改原数组)。 - 为什么不能
arr[-1]:方括号按属性名取值,arr[-1]实际是arr["-1"],与数组长度无关。 - 通用性:方法是 generic 的,只要有
length和整数键即可;String、TypedArray 也有同名at()。
示例代码
正数、负数、越界(本地已跑通):
const arr = [5, 12, 8, 130, 44];
console.log(arr.at(2)); // 8,等同 arr[2]
console.log(arr.at(-1)); // 44,最后一个
console.log(arr.at(-2)); // 130,倒数第二个
console.log(arr[-1]); // undefined!不是最后一个
console.log(arr[arr.length - 1]); // 44,旧写法
console.log(arr.at(99)); // undefined
console.log(arr.at(-99)); // undefined
取购物车最后一项,比手算 length 干净:
const cart = ["apple", "banana", "pear"];
function returnLast(list) {
return list.at(-1);
}
console.log(returnLast(cart)); // "pear"
cart.push("orange");
console.log(returnLast(cart)); // "orange"
三种取「倒数第二个」的对比(MDN 同款思路):
const colors = ["red", "green", "blue"];
const lengthWay = colors[colors.length - 2]; // "green"
const sliceWay = colors.slice(-2, -1)[0]; // "green",多包一层数组
const atWay = colors.at(-2); // "green",最直接
字符串同样可以:
console.log("hello".at(-1)); // "o"
需要「相对下标写回」时用 with()(返回新数组):
const nums = [1, 2, 3];
const next = nums.with(-1, 42); // [1, 2, 42]
console.log(nums); // [1, 2, 3],原数组不变
常见误区
-
以为
arr[-1]能取最后一个
不能。它读的是属性"-1"。赋值arr[-1] = 99还会在数组对象上多出一个非索引属性,length不变,at(-1)仍是真正的末项。 -
用
at()当左值赋值
at()只返回值,没有 setter。要改相对位置请用with(),或先算正数下标再用方括号。 -
把
slice(-1)当成at(-1)
slice(-1)返回长度为 1 的新数组;at(-1)返回元素本身。取单个值时别混。 -
忘记越界是
undefined
空数组[].at(-1)是undefined,和arr[arr.length - 1]在空数组上的行为一致,但别误当成抛错。 -
老环境未 polyfill 就上线
Safari 要到 15.4 才有。若还要兼容更旧 WebView,查 Can I use 或加 polyfill;现代 evergreen 浏览器与 Node 16.6+ 一般没问题。
小结
取倒数第 n 个,优先 arr.at(-n):比 length - n 好读,也比误用 arr[-1] 正确。它是只读访问;越界返回 undefined;写回相对下标用 with()。字符串同样有 at()。正式项目以 MDN Array.prototype.at() 与目标运行时兼容表为准。
参考资料
谢谢你读到这里。