DEV Community

Thomas Barrasso
Thomas Barrasso

Posted on

2 1

TC39 proposal: Array.lastItem

A recent TC39 proposal offers easier access to the last element in a JavaScript Array. While on the surface this does not seem significant, there are many benefits to such a proposal.

Terminal elements are unique in that they tend to be accessed more often than middle elements. Because of this, many other scripting languages like Ruby and Python provide convenience methods and properties to access and modify them.

The only way to do this in ES6 is with indices. But even a trivial task like swapping the last elements in two arrays quickly becomes difficult to read.

let faces = ["πŸ˜€", "πŸ˜‰", "πŸ€‘", "😏", "🐐"];
let animals = ["πŸ’", "πŸ•", "🐈", "🐎", "πŸ™„"];
let lastAnimal = animals[animals.length - 1];
animals[animals.length - 1] = faces[faces.length - 1];
faces[faces.length - 1] = lastAnimal;
view raw without_lastItem.js hosted with ❀ by GitHub

The most common solution today is to use libraries like Lodash or Underscore that include utility functions for accessing the last element. This offers an improvement in clarity, but introduces several complications. Most obviously, they do not include a way to set the last element. Even if they did, doing so would add ambiguity by removing the = assignment operator.

let faces = ["πŸ˜€", "πŸ˜‰", "πŸ€‘", "😏", "🐐"];
let animals = ["πŸ’", "πŸ•", "🐈", "🐎", "πŸ™„"];
let lastAnimal = _.last(animals);
animals[animals.length - 1] = _.last(faces);
faces[faces.length - 1] = lastAnimal;
view raw underscore_last.js hosted with ❀ by GitHub

That is where the ECMAScript Technical Candidate (TC39) proposal comes in. In its current form, it introduces two new properties: Array.lastItem and Array.lastIndex. The first property is especially useful because it works both for setting and getting the last item.

let faces = ["πŸ˜€", "πŸ˜‰", "πŸ€‘", "😏", "🐐"];
let animals = ["πŸ’", "πŸ•", "🐈", "🐎", "πŸ™„"];
let lastAnimal = animals.lastItem;
animals.lastItem = faces.lastItem;
faces.lastItem = lastAnimal;
view raw array_lastItem.js hosted with ❀ by GitHub

This proposal is actually already supported in core-js 3 and can be used with Babel and TypeScript today. However, I do not have much use for Array.lastIndex and would prefer a symmetrical for the first element. For prototypes and smaller projects I wrote two simple, dependency-free properties that do just that.

if (!Array.prototype.last) {
Object.defineProperty(Array.prototype, 'last', {
enumerable: false,
configurable: false,
get() {
return this[this.length - 1]
},
set(value) {
return this[Math.max(0, this.length - 1)] = value
},
});
}
if (!Array.prototype.first) {
Object.defineProperty(Array.prototype, 'first', {
enumerable: false,
configurable: false,
get() {
return this[0]
},
set(value) {
return this[0] = value
},
});
}
view raw first_and_last.js hosted with ❀ by GitHub

I recently learned that destructuring in ES6 can swap array elements without temporary variables. This is a great example of where Array.first and Array.last can really improve clarity.

let nums = [5, 2, 3, 4, 1]
# With indices
[nums[nums.length-1], nums[0]] = [nums[0], nums[nums.length-1]]
# With Array.first & Array.last
[nums.last, nums.first] = [nums.first, nums.last]
view raw first_last_example.js hosted with ❀ by GitHub

Suggestions of properties like Array.first and Array.last go back to at least 2013. Hopefully this Stage 1 proposal continues to get traction and will be coming to a version of JavaScript near you soon.

Image of Timescale

πŸš€ pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applicationsβ€”without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read full post β†’

Top comments (3)

Collapse
 
devinrhode2 profile image
Devin Rhode β€’

Array.last is on pause in favor of a few other proposals...

This proposal's champion (@keithamus) does not plan to advance to Stage 2 for now. Other proposals (Array.prototype.item and Array Slice Notation) also sufficiently solve this problem, and are advancing quicker through the standards track. Should one of these proposals advance to Stage 3, this proposal will be dropped.

Collapse
 
healeycodes profile image
Andrew Healey β€’

Array.first and Array.last are interesting proposals. Thanks for the clear examples. I've always thought Python's [-1] accessor for the last element was very elegant.

Collapse
 
tombarr profile image
Thomas Barrasso β€’

Thanks for the kind words. I'm mixed on negative indices. They are more powerful than a single Array.last property because they let you easily access say, the second to last element [-2]. But I don't find them that much clearer.

That said, JavaScript will likely never get support for negative indices because Array is just an Object, and [-1] is a valid property on either. This would introduce a break change to the language (although it's a pretty bad idea using an Array as a map).