JavaScript is evolving. Every day, new language ideas and features are discussed and proposed. The TC39 committee is responsible for the specification and development of the ECMAScript (JavaScript) language.
TC39 operates by consensus and has the discretion to alter the specification as it sees fit. However, the general process for making changes to the specification is as follows.
Each new language feature has four stages, with each stage representing how far the feature is from being implemented. Stage three features are usually soon to be implemented — but that does not mean they always will be!
The TC39 Process — https://tc39.es/process-document/
Let’s take a look at the most promising and exciting stage three features currently being discussed.
Please keep in mind: none of these features are final and all are subject to change. The upside is that if a new feature is to be implemented officially, we’ll already be up to speed and know the how-and-why.
When looking for a property value deep in a tree-like structure, one often has to check whether intermediate nodes exist:
const street = user.address && user.address.street;
file.js
checking if the user has an address and street address
Say we’re iterating over an array:
const data = []
data.map(item => <div>{item}</div>)
file.js
looping over data
What happens if the data variable is null
or undefined
?
We’d get an error like type error: cannot read property ‘data’ of undefined.
This usually happens when we fetch data over an API and we’re looping over the data before the request has been finished.
The solution is to check whether our data exists and isn’t empty by checking the array length:
if (data && data.length > 0) {
data.map(item => <div>{item}<div>)
}
/* or */
data && data.length > 0 && data.map(item => <div>{item}<div>)
propChecking.js
It works, but it’s bulky. How can we improve the code above? You may have heard that languages such as TypeScript or Swift have features called optionals.
The Optional Chaining Operator allows a developer to handle many of those cases without repeating themselves and/or assigning intermediate results in temporary variables. The Optional Chaining Operator looks like this:
const street = user.address?.street
optional.js
That’s it! A simple question mark to check whether the user has the address
property. If they have the address
property, access the street
property.
Remember the data fetching example? Well, we can improve the code with a simple question mark:
data?.map(item => <div>{item}<div>
optionalMap.js
Check if data exists, and if it does, map over the data.
The call variant of Optional Chaining is useful for dealing with interfaces that have optional methods:
iterator.return?.() // manually close an iterator
optional.js
The Optional Chaining operator is spelled ?.
and it may appear in three positions:
obj?.prop // optional static property access
obj?.[expr] // optional dynamic property access
func?.(...args) // optional function or method call
optional.js
If you found this feature useful, read the full specifications here. The discussion is open to anyone.
I know, what a goofy name! Not to worry, it sounds scary but it’s not.
When performing property accesses, it is often desirable to provide a default value if the result of that property access is null
or undefined
. At present, a typical way to express this intent in JavaScript is by using the ||
operator:
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
const undefinedValue = response.settings.undefinedValue || 'some other default'; // result: 'some other default'
const nullValue = response.settings.nullValue || 'some other default'; // result: 'some other default'
file.js
This works well for the common case of null
and undefined
values, but there are several of falsey values which might produce surprising results.
// Potentially unintended. '' is falsy, result: 'Hello, world!'
const headerText = response.settings.headerText || 'Hello, world!';
// Potentially unintended. 0 is falsy, result: 300
const animationDuration = response.settings.animationDuration || 300;
// Potentially unintended. false is falsy, result: true
const showSplashScreen = response.settings.showSplashScreen || true;
file.js
The nullary coalescing operator is better at handling these and serves as an equality check against nullary values such as null
or undefined
If the expression at the left-hand side of the ??
operator evaluates to undefined or null, its right-hand side is returned:
const response = {
settings: {
nullValue: null,
height: 400,
animationDuration: 0,
headerText: '',
showSplashScreen: false
}
};
// result: 'some other default'
const undefinedValue = response.settings.undefinedValue ?? 'some other default';
// result: 'some other default'
const nullValue = response.settings.nullValue ?? 'some other default';
// result: ''
const headerText = response.settings.headerText ?? 'Hello, world!';
// result: 0
const animationDuration = response.settings.animationDuration ?? 300;
// result: false
const showSplashScreen = response.settings.showSplashScreen ?? true;
nullary.js
Here are some key takeaways for the Nullish Coalescing Operator.
??
is evaluated only if needed (“short-circuiting”).??
has lower precedence than ||
.??
cannot immediately contain, or be contained within, an &&
or ||
operation.null
or undefined
.Read the full specification here. Jump into the public discussion here.
If you know JavaScript well enough, you probably know JavaScript is bad at handling numbers. BigInt is an attempt to improve integers for JavaScript.
BigInt
is a new primitive that provides a way to represent whole numbers larger than 253, which is the largest number Javascript can reliably represent with the Number
primitive:
const x = Number.MAX_SAFE_INTEGER;
// ↪ 9007199254740991, this is 1 less than 2^53
const y = x + 1;
// ↪ 9007199254740992, ok, checks out
const z = x + 2
// ↪ 9007199254740992, wait, that’s the same as above!
numbers.js
A BigInt
is created by appending n
to the end of the integer or by calling the constructor:
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n
const hugeButString = BigInt('9007199254740991');
// ↪ 9007199254740991n
BigInt.js
Check out the BigInt proposal in-depth right here. If you know Math, please give feedback to the committee.
This proposal adds three features to JavaScript classes, building on the previous class fields and private methods proposals:
It’s hope that declaring static properties in the class body will be cleaner and do a better job of meeting programmer expectations of what classes should be for.
class CustomDate {
// ...
static epoch = new CustomDate(0);
}
/* or */
class CustomDate {
// ...
}
static.js
To make fields private, just give them a name starting with a #
:
class Counter extends HTMLElement {
#x = 0;
clicked = () => {
this.#x++;
window.requestAnimationFrame(this);
}
constructor() {
super();
this.onclick = this.clicked.bind(this);
}
connectedCallback() { this.render(); }
render() {
this.textContent = this.#x.toString();
}
}
window.customElements.define('num-counter', Counter);
CounterClass.js
To make methods, getter/setters or fields private, also give them a name starting with a #
:
class Counter extends HTMLElement {
#xValue = 0;
get #x() { return #xValue; }
set #x(value) {
this.#xValue = value;
window.requestAnimationFrame(this.#render.bind(this));
}
#clicked() {
this.#x++;
}
constructor() {
super();
this.onclick = this.#clicked.bind(this);
}
connectedCallback() { this.#render(); }
#render() {
this.textContent = this.#x.toString();
}
}
window.customElements.define('num-counter', Counter);
CounterClass.js
Note that this proposal provides private fields and methods only as declared up-front in a field declaration. Private fields cannot be created later, ad-hoc, by assigning to them, the way normal properties can.
You also cannot declare private fields or methods in object literals. For example, if you implement your class based on object literals, or adding individual methods to the prototype, or using a class framework, you cannot use private methods, fields or accessors.
There are many more proposals and I urge you to take a look at them. Everyone has a say, and a vote, your voice matters for shaping the future of the JavaScript language.
See the full list of proposals here.
In case you want to bring your JavaScript game to the next level, I’d suggest grabbing the “You Don’t Know JS” book series. I found it to be easy to understand and useful.
Thanks for reading, stay awesome.
☞ JavaScript Programming Tutorial Full Course for Beginners
☞ Learn JavaScript - Become a Zero to Hero
☞ Javascript Project Tutorial: Budget App
☞ E-Commerce JavaScript Tutorial - Shopping Cart from Scratch