Hi All!
I was very lucky to have TC39 conveniently hosted at my home-campus – Microsoft in Redmond Washington – this July. It made for a very easy commute, and an enjoyable time.
Starting off on a non-code note, TC39 has elected a new chair – Rex Jaeschke. Rex will serve in this capacity for the September and November meetings as a trial period. At that time, the committee will vote on whether to move forward with him permanently. In addition, the committee elected Leo Balter and Dan Ehrenberg as vice-chairs who will help Rex as he learns the ropes of TC39.
Rex brings an exceptional resume to TC39. He authored the PHP and Hack specifications, and is also currently serving as the editor of the standard for the C# programming language. I very much look forward to what Rex can bring to the table as we continue to grow as a committee, and focus on improving diversity.
July had an unusually packed schedule, and I couldn’t possibly write a blog post that covers everything, but here are some proposal highlights from the meeting:
Optional Catch Binding
In the ‘common sense prevails’ category, I’m happy to report that Optional Catch Binding advanced from stage 0 to stage 3. This is a simple but very necessary change. In the past, it was required to pass a variable to a catch block, like this:
try { } catch(e) { }
With this proposal, the following is sufficient:
try { } catch { }
This is a simple change, but one I very much appreciate. Why type what you don’t need?
Fields and Private Methods
The class fields proposal advanced to stage 3.
The start of this proposal may seem un-intuitive to developers at first glance, but it actually enables some wonderful things. The first thing this proposal does is allow someone to define fields on a class:
export class Cat { Name; Age = 4; }
If you want to, you can also define static fields on the class, which are attached to the prototype object instead of the instance:
export class Cat { Name; Age = 4; static Noise = 'Meow'; }
So why would we want to do this? Well, first of all, it provides serious perf gains to the runtime by allowing the runtime to know what fields will be on the class up-front. It does this by ensuring that, behind the scenes, all fields are declared in the class constructor.
But perhaps most awesome for library authors in the world (and everyone else too), is that the ability to declare a field enables us to make a field private! For instance, if I want the noise a cat makes to be internal:
export class Cat { Name; Age = 4; static #Noise = 'Meow'; makeNoise() { return Cat.#Noise; } }
Now, I don’t know about everyone else, but for me that right there is a game-changer. I don’t know how many times I’ve had to repeat myself on Moment’s GitHub: “The fields marked with an _ are private, don’t use them!”
My problems are solved! Actual private fields! Just add #.
But it gets even better than that.
Private Methods
Private methods advanced to stage 2. Private methods piggyback on the work in the class fields proposal that advanced to stage 3.
export class Cat { Name; Age = 4; #rightFrontLeg = 0; #leftFrontLeg = 0; static #Noise = 'Meow'; makeNoise() { return #Noise; } #moveRightFrontLeg() { this.rightFrontLeg++; } #moveLeftFrontLeg() { this.leftFrontLeg++; } batPaws () { this.#moveRightFrontLeg(); this.#moveLeftFrontLeg(); } }
Having highlighted all concepts of private fields previously, I think that the code probably speaks for itself. The individual methods for moving the cat’s legs are inaccessible outside the class, because the methods have been marked private.
Promise.prototype.finally
The proposal for Promise.prototype.finally brings a feature that is immensely popular in the libraries Q
and bluebird
. This feature allows the user to ‘clean up’ after a promise is completed, regardless of whether it was a success or failure. The following code illustrates a typical use case for finally, where an HTTP request is being timed for debugging purposes. Regardless of success or failure, upon return of the promise, the time should log.
function getThing(uri) { const time = performance.now(); fetch(uri).then(result => { return result; }).catch(err => { //log error somewhere }).finally(()=>{ console.log(performance.now() - time); }) }
In Closing
It is with both happiness and regret that I mention that longtime JS Foundation representative to TC39, Leo Balter, has changed his delegate status to being a representative of his employer, Boucoup. I am happy because Leo has gotten the support of his employer to make TC39 a ‘day job’ kind of thing. This is definitely best for him. I also say this with regret because Leo has always been a passionate advocate on the committee of some things that JS Foundation holds most dear, including being the driving force behind the new code of conduct, and a continual champion of diversity and inclusion. I look forward to continuing to work with Leo on many great things.
I remain the JS Foundation’s representative to TC39. In this capacity, I wish to bring the voice of the community to all TC39 activities. If you wish to contribute ideas to the standard, feel free to get in contact with me. DMs are always open on twitter.
There are some amazing proposals headed toward us in ECMAScript, and I’m incredibly excited for what is coming!