Safely Read the Last Element
Reading `array[array.length - 1]` is the line every JavaScript developer writes a thousand times, and a chunk of those calls hide bugs on empty arrays or computed expressions. Modern `Array.prototype.at(-1)` makes the intent obvious and supports negative indexes natively. This snippet shows the modern form, the safe-default helper for empty inputs, and the typed-array story so you pick the right tool.
523 views
13
const items = ['a', 'b', 'c'];
console.log(items.at(-1)); // 'c'
console.log(items[items.length - 1]); // 'c'
// at() also works on strings and typed arrays
console.log('hello'.at(-1)); // 'o'
console.log(new Int32Array([10, 20, 30]).at(-1)); // 30Array.prototype.at(index) accepts negative indexes that count from the end, which is the cleaner spelling of the classic array[array.length - 1]. It is supported on every evergreen runtime (Node 16.6+, all modern browsers). The savings get bigger when the array is the result of a computed expression: getRows().at(-1) runs the call once, while getRows()[getRows().length - 1] runs it twice and breaks if the function is non-idempotent. It also reads as plain English, which matters more than micro-optimisation.
function last(array, fallback) {
return array.length > 0 ? array[array.length - 1] : fallback;
}
console.log(last([1, 2, 3], 0)); // 3
console.log(last([], 0)); // 0
console.log(last([], null)); // null
console.log(last(['only'], '!')); // 'only'Both array.at(-1) and array[array.length - 1] return undefined for an empty array, which is fine until you destructure or call a method on the result. A tiny last(array, fallback) helper makes the empty case explicit at the call site, and TypeScript users get a clean T | F return type for free. This is one of those three-line utilities worth committing to a utils/array.ts rather than re-deriving in every component. Keep fallback as a value, not a thunk, unless you genuinely need lazy evaluation.
const stack = [1, 2, 3];
// peek without mutating
const top = stack.at(-1);
console.log(top); // 3
console.log(stack); // [1, 2, 3]
// pop both reads and removes
const popped = stack.pop();
console.log(popped); // 3
console.log(stack); // [1, 2]The bug that hides in array.pop() is that it mutates the array. If you only meant to read the last item, at(-1) is the right choice and your function stays pure. Reach for pop() only when stack semantics are actually wanted (undo history, depth-first search, expression evaluation). When the array is Object.freezed or an immutable proxy, pop() will throw or silently fail, while at(-1) always works. The same distinction applies to shift() versus at(0) for the front of the array.
