Что такое Array.prototype.at() в JavaScript и чем он отличается от обращения через []?
Зачем нужен Array.prototype.at()
Метод at() появился в ES2022 и предназначен для получения элемента массива (а также строки и типизированных массивов) по индексу с поддержкой отрицательных значений. До его появления единственным способом обратиться к элементу с конца массива было писать arr[arr.length - 1] или использовать slice(-1)[0].
const arr = [10, 20, 30, 40, 50];
console.log(arr.at(0)); // 10
console.log(arr.at(-1)); // 50, последний элемент
console.log(arr.at(-2)); // 40, предпоследний элемент
Чем at() отличается от квадратных скобок
Обращение через [] не понимает отрицательные индексы — они трактуются как обычные строковые ключи объекта, поэтому arr[-1] вернёт undefined, если такого свойства нет. Метод at() приводит переданное значение к целому числу, и если оно отрицательное, отсчитывает позицию с конца массива: arr.at(-1) эквивалентно arr[arr.length - 1].
const arr = [1, 2, 3];
arr[-1]; // undefined, обычное свойство объекта
arr.at(-1); // 3, последний элемент
Поведение при выходе за границы
Если индекс выходит за пределы массива в любую сторону, at() возвращает undefined, не выбрасывая исключения — так же, как ведёт себя обращение через [].
[1, 2, 3].at(10); // undefined
[1, 2, 3].at(-10); // undefined
Где ещё применяется at()
Аналогичный метод добавлен в String.prototype, а также в типизированные массивы (Int32Array, Uint8Array и другие), поэтому синтаксис одинаково работает и со строками.
const str = 'hello';
str.at(-1); // 'o'
Практическая польза
Главное преимущество — читаемость кода: arr.at(-1) короче и понятнее, чем arr[arr.length - 1], особенно в цепочках вызовов без промежуточной переменной с длиной.
// без at() пришлось бы сохранять промежуточный результат в переменную
const last = getItems().at(-1);
Поддержка в средах выполнения
Метод поддерживается всеми современными браузерами и Node.js начиная с версии 16.6+, но отсутствует в старых окружениях (например, Node 14), поэтому при необходимости стоит использовать полифилл или транспиляцию через Babel/core-js.
Что хочет услышать интервьюер
Кандидат знает, что at() принимает отрицательные индексы для обращения с конца массива
Понимает отличие от arr[-1], которое не работает так же, как at(-1)
Знает, что метод возвращает undefined при выходе за границы массива, а не выбрасывает ошибку
Осведомлён, что at() также есть у строк и типизированных массивов
Понимает, что это относительно новая фича (ES2022) и может потребовать полифилла
Пример: Базовое использование at()
const arr = [10, 20, 30, 40, 50];
console.log(arr.at(0)); // 10
console.log(arr.at(-1)); // 50
console.log(arr.at(-2)); // 40
console.log(arr.at(100)); // undefined
Пример: at() vs квадратные скобки
const arr = [1, 2, 3];
// квадратные скобки не понимают отрицательные индексы
console.log(arr[-1]); // undefined
// at() отсчитывает позицию с конца массива
console.log(arr.at(-1)); // 3
// работает и со строками
console.log('hello'.at(-1)); // 'o'
Типичные ошибки
Считают, что arr[-1] работает так же, как arr.at(-1)
Путают at() с методами indexOf/findIndex, которые ищут индекс по значению, а не наоборот
Используют at() только с положительными индексами, не зная о поддержке отрицательных
Не учитывают необходимость полифилла/транспиляции для старых окружений вроде Node 14
Путают at() с деструктуризацией или slice() для получения последнего элемента


