Proposals
The features that I mention in this article have been proposed to TC39, the committee that moves JavaScript forward, but are not yet part of the standard that JavaScript conforms to.
There are 5 stages that a proposal goes through to land in JavaScript: Strawman, Proposal, Draft, Candidate, and Finished.
All of the following features are stage 1 proposals, which means they have met the guidelines for what a proposal must be, and have been presented to TC39. If you're interested in learning more about proposals and the process, head over to the official TC39 proposals repo.
Now, to the proposals!
Last Item
lastItem
is proposed to be added to the array prototype, which would make it super easy to grab the last item in an array. I love this feature, because I think it's a step in the right direction to solve some common ergonomics issues in JavaScript.
const food = ['🌮', '🥑', '🥓'];
/* New syntax */
const bacon = food.lastItem; // 🥓
/* Old syntax */
const bacon = food[food.length - 1];
Optional Chaining
Optional Chaining is a proposal that streamlines the access of properties on potentially null
or undefined
types.
The reason we need this is because if object.thing
isn't defined, and you write object.thing.test
, JS won't just return null
or undefined
, it will actually throw an error: 🚩"Cannot read property 'test' of undefined".
const inputElement = document.querySelector('input[name=email]');
/* New Syntax */
const street = user.address?.street; // returns street value, or null
const inputValue = inputElement?.value; // returns input value, or null
/* Old Syntax */
const street = user.address && user.address.street;
const inputValue = inputElement ? inputElement.value : undefined;
How it works: If the item before the ?
is null
OR undefined
, it will return null without processing the next item, otherwise it processes the next bit of the "chain". So in the example above, if the object user
doesn't have a key of address
, then it will return null
. If it does, it will process the .street
part, and return the value of user.address.street
.
I was not a fan when I first saw this proposal, but I've come around on it. The syntax is a bit funky, but it will definitely simplify your codebase.
Null(ish) Coalescing Operator
This proposal allows you to check if a variable or statement is undefined
or null
and return a fallback value if it is.
/* New Syntax */
const one = undefined ?? 'Fallback'; // 'Fallback'
const two = null ?? 'Fallback'; // 'Fallback'
/* Old Syntax */
const one = undefined || 'Fallback';
const two = null || 'Fallback';
From looking at the above examples, you might think the Null Coalescing operator is totally unnecessary because it does the same thing as the OR operator. But they behave differently.
/* The differences between ?? and || */
const diffOne = 0 ?? 'Fallback'; // 0
const diffOne = 0 || 'Fallback'; // 'Fallback'
const diffTwo = '' ?? 'Fallback'; // ''
const diffTwo = '' || 'Fallback'; // 'Fallback'
const diffThree = false ?? 'Fallback'; // false
const diffThree = false || 'Fallback'; // 'Fallback'
How it works: The null coalescing operator returns the first thing that isn't null
or undefined
.
This is different from the way we usually check variables using ||
because the OR operator returns the first thing that's truthy. This means that if the value is false
, an empty string, or null
, it will not be returned; That can be a problem if one of those (false, null, empty string) is a valid value.
Do Block
The "do block" is a very interesting proposal, but it takes some getting used to. The syntax is simple: you write do
, and then in brackets code you'd like to be executed. This feature would allow you to do some cool things that have been hard (or seemed hacky) in the past. Like when you have complex criteria for how to define a variable:
/* New Syntax */
const x = do {
if (foo()) { f() }
else if (bar()) { g() }
else { h() }
};
/* Old Syntax */
let x = foo() ? f() : bar() ? g() : h();
// OR
let x = (() => {
if (foo()) return f();
else if (bar()) return g();
else return h();
}();
As mentioned in the official proposal, this syntax is especially helpful when used in templating languages like JSX.
return (
<nav>
<Home />
{
do {
if (loggedIn) {
<LogoutButton />
} else {
<LoginButton />
}
}
}
</nav>
);
Replace All
Wait, why do we need this again? We were already able to do string.replace('this', 'that')
, right? But, replace
only replaced the first instance of a string, unless you used a Regex. Again, this features solves a common "small problem" and makes things easier, especially for beginners 😄.
const string = '248.434.5508';
/* New syntax */
string.replaceAll('.', '-'); // returns '248-434-5508'
/* Old syntax */
string.replace(/\./g, "-");
Learning More
If you're interested in learning more about any of these potential features, you can check out the links to the official proposals below, or you can review all of the JS proposals.
- Last Item: https://github.com/keithamus/proposal-array-last
- Optional Chaining: https://github.com/tc39/proposal-optional-chaining
- Null(ish) Coalescing Operator: https://github.com/tc39/proposal-nullish-coalescing
- Do Block: https://github.com/tc39/proposal-do-expressions
- Replace All: https://github.com/tc39/proposal-string-replace-all
Top comments (2)
I really like the optional chaining operator and the null coalescing operator in Kotlin and I'd love to see them in JS. The latter is called "Elvis operator" (
?:
) in Kotlin, btw.Yeah, both of those are really cool and helpful features. Thanks for sharing about the "Elvis operator" I didn't know that!