先记住这个答案
at(index) 按相对位置读取数组元素,负数通常从末尾计数,at(-1) 返回最后一项;arr[-1] 则访问名为 "-1" 的普通属性,不会自动换算成最后索引。at 越界返回 undefined,空数组也没有最后一项,且它只读取值,不提供赋值语法。at 属于 ES2022 标准功能,但旧浏览器或旧运行时可能没有,需要按支持目标检测或使用合适兼容方案。若只需普通数组最后一项,arr[arr.length - 1] 可以明确表达回退,但不等于完整实现所有 at 参数规则。
- 负数方括号是普通属性访问
- at 越界返回 undefined,不会循环取模
- 语法转译不能自动补齐缺失的原型方法
给数组增加负数属性后差异更明显
常见回答说 arr[-1] 总是 undefined,这忽略了数组仍是对象。下面显式添加名为负一的属性,方括号可以读到它,而 at(-1) 仍按数组长度定位最后一项。
该属性不会让 length 增加,也不成为通常意义上的数组元素。调试时应把业务索引与对象附加属性分开,不要利用这种写法模拟 Python 式负索引,再期待数组方法自动识别它。
const values = ['first', 'last'];
values[-1] = 'metadata';
console.log(values.at(-1));
console.log(values[-1]);
console.log(values.length);
console.log(values.at(-3) === undefined);
console.log([].at(-1) === undefined);查看输出与解释
last
metadata
2
true
trueat 根据长度二计算最后位置一,不读取负一属性。超出左边界时不会绕回数组尾部,空输入同样返回 undefined,因此调用方需要定义无结果分支。
取最后一项时仍要处理无结果
例如读取最近一次操作记录,空记录列表可能是正常初始状态,应显示明确的空状态或跳过后续处理。直接对 at(-1).id 访问属性会在空数组时失败,方法本身不会替业务创造记录。
可选链可以避免属性访问异常,但还需要决定 undefined 对业务意味着什么。若元素允许本身为空,应区分没有元素与存在空值;单独比较返回值不足以完成这种校验。
兼容策略应覆盖实际执行环境
TypeScript 的库声明让代码通过类型检查,不代表旧运行时真的有 Array.prototype.at。构建工具处理新语法与补充内建方法是不同能力,应按浏览器、SSR 和脚本环境分别确认支持。
只取末项可以写明确索引表达式;若封装任意相对索引,需要覆盖负数、越界和整数转换等规则。完整 polyfill 应使用维护中的标准实现并验证目标环境,不宜用一个取模函数冒充规范行为。
容易答错的地方
- 认为方括号负索引总是取不到任何值
- 它可以读取同名普通属性,只是不按数组位置解释。回答应说明默认数组通常没有该属性,而不是把常见结果说成语言禁止,以免在自定义属性场景下得出错误结论。
- 用取模实现负索引兼容
- 取模可能把过小或过大的索引绕回有效位置,而标准 at 对越界返回 undefined。若需求只是最后一项应直接写该操作;实现通用兼容时必须保留边界与参数转换语义。
面试官还会怎么问?
能写 arr.at(-1) 等于新值来修改数组吗?
不能,函数调用结果不是可赋值的引用位置。修改末项需要明确计算索引并确认数组非空,或使用符合状态更新约定的复制方式;读取便利并不提供新的赋值语法。
at(1.9) 会读取小数属性吗?
at 会进行整数转换,普通有限小数会向零截断后作为位置读取,不是直接访问名为 1.9 的属性。外部输入仍应先校验业务允许的索引类型,避免依赖隐式转换掩盖参数错误。
字符串也有 at,能直接按用户字符切分吗?
字符串 at 读取的是相应 UTF-16 码元位置,不能自动按完整表情或字素簇处理。数组位置便利与自然语言字符分割属于不同问题,处理用户可见字符需要选择合适的分段方式。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。