Ever since the release of ECMAScript 6 (ES6), JavaScript has been enjoying a very lively and vibrant development. Thanks to the now-yearly release cycle of the ECMA-262 standard and hard work of all browser vendors, JS rose to become one of the most popular programming languages in the world!
In my recent article, I covered all the new features introduced to the latest release of JS specification - ES2020. While some were quite interesting, none of them were "ground-breaking". But that's understandable given the current, more frequent update cycle of the specification. There's simply less room for special features like ES6 modules or arrow functions to appear every year.
But it doesn't mean that they won't come eventually which brings us to the topic of this article. Here, I'd like to walk you through 4 of what, in my opinion, are potentially ground-breaking JavaScript features that are currently at different stages of the approval process. Which, granted - means that we might never see them actually being implemented - but it still should make some pretty insightful experience anyway. Let's get into it!
Decorators
Let's start with arguably the most requested and hyped feature that's been making the headlines for a couple of years now - decorators.
You might be already familiar with them - especially if you're a TypeScript user. They're essentially a meta-programming concept meant to allow you to "inject" custom functionalities into your classes, their individual fields, and methods, effectively making them programmable.
Consider the following example:
function sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
Now, I decided to play it safe and go with simple TypeScript decorators example - mainly to demonstrate the general concept. Above, we create the sealed
decorator and apply it to the Greeter
class. As you can see, here, the decorator is simply a function that gets access to the constructor of the class it's applied to (aka target). We use this reference with Object.seal()
to make our class effectively not extensible.
To apply the decorator to our class, we write it just above our target - in this case, a class - with the @[name]
syntax (e.g. @sealed
).
You can verify that our decorator is working by compiling the above TypeScript code with experimentalDecorators
option enabled, and trying to alter our class' prototype:
Greeter.prototype.test = "test"; // ERROR
With that said, you should now have a basic understanding of what decorators are about. But there's one more issue I'd like to address - and that's the current state of this feature.
There's a reason I decided to use the TypeScript implementation in the example above. It's been a few years since the decorator proposal originally appeared, and it's still "only" at stage 2 of 4 stage approval process. There are changes actively being made both to the syntax as well as the functionalities of the decorators. But this didn't stop the JS community from early-adopting the concept - just look at huge open-source projects such as TypeScript or Angular v2+.
However, this raises the problem of specification incompatibilities as time goes on and the proposal evolves. There's been a pretty substantial overhaul of decorators specification since their introduction, and most projects have still not implemented it. The TypeScript example I showcased earlier implements the older version. So does Angular and even Babel (although here the implementation of the newer version is in progress). Overall, the newer version with the decorator keyword and composable syntax, haven't seen any kind of mass-adoption just yet.
To sum it all up, decorators do have the potential to change the way we write our code and that's already visible through their current early-adoption rate. However, at the current stage, they've only fractured the community and, in my opinion, still aren't ready for prime time. So, unless you're using a framework that relies on decorators (like Angular), I'd say you should hold on a little bit longer before using decorators in your production projects.
Realms
Slowing down a little, let's talk about something less complicated than decorators - Realms.
You might have already been in scenarios where you need to run your own or third-party code, but don't want to affect your global environment. Many libraries - especially in the browser - work through the global window
object and thus can overlap when you use too many uncontrolled libraries at the same time, resulting in errors.
Currently, the solution for that in browsers are iframes and for more specific tasks - Web Workers, while on the Node.js side - the vm
module or child processes. And that's where Realms API comes into play.
This proposed API is meant to allow you to create distinct global environments called Realms, with each such environment having its own globals. Take a look:
var x = 39;
const realm = new Realm();
realm.globalThis.x; // undefined
realm.globalThis.x = 42; // 42
realm.globalThis.x; // 42
x; // 39
In the example, we create a new Realm using the Realm
constructor. From this point on, we've got complete access to our new Realm and its global object through the globalThis
property (introduced in ES2020). You can see that variables are kept separate and distinctive between the main "incubator" Realm and the one we've created.
Overall, Realms API aims to be a very simple, yet useful feature. It has a very specific set of use-cases - it doesn't provide improved security nor multi-threaded capabilities. But for what it does - basic environment sandboxing without much overhead - it's a very capable API.
Realms are currently at stage 2, and when they eventually come, you can expect to see them used in heavily global-dependent libraries, online sandbox code editors, and various testing applications.
Do expressions
Like most languages, JavaScript syntax incorporates both statements and expressions. The most noticeable difference between these constructs is the fact that expressions can be used as values (thus they can be assigned to variables, passed to function calls, etc.), while statements cannot.
Because of this difference, expressions are often favored as the way for cleaner and more compact syntax. In JS this can be seen by looking at the popularity of function expressions (including arrow functions) over function statements, various array iteration methods (like forEach()
) in comparison to loops and - for more advanced developers - ternary operator vs if
statements.
Stage 1 do
expressions proposal (not to be confused with do...while
loop, which is an entirely different thing) aims to push the boundaries of JS expressions even further.
let x = do {
if (foo()) {
f();
} else if (bar()) {
g();
} else {
h();
}
};
In the example above you see the proposed syntax for the do
expressions. Essentially it's a piece of JS code, wrapped inside do {}
, last expression of which is "returned" as the end value of the entire do expression.
Similar if not identical effect can be already achieved using Immediately Invoked Function Expressions (IIFEs), but it's the compact syntax that's most compelling here. You don't need any return
s or the same amount of ugly wrapping code (e.g. (() => {})()
), while still getting access to all the functionalities. That's why I think when they come out, their impact could be similar to ES6 arrow function. The convenience of expressions and friendly syntax in a single package sounds just so good!
Pattern matching
Last but not least, I'd like to talk about the pattern matching proposal.
You might be familiar with the JS switch
statement. It's similar to using if
/else
but is a bit more limiting and certainly more suitable for handling a large number of different case
s.
switch (value) {
case 1:
// ...
break;
case 2:
// ...
break;
case 3:
// ...
break;
default:
// ...
break;
}
Personally, I find switch statement inferior to if
/else
due to its value-comparison-only limitations (you can get around that, but I don't know why you'd even want to) and the verbose syntax with repetitive break
statements.
Now, you can think of pattern matching as a more feature-rich, expression-based, and potentially much more versatile version of the switch
statement. Instead of simple value comparison, pattern matching allows you to - as the name implies - match values to specific patterns that are heavily customizable. Here's a fragment of the proposed API:
const getLength = vector => case (vector) {
when { x, y, z } -> Math.hypot(x, y, z)
when { x, y } -> Math.hypot(x, y)
when [...etc] -> vector.length
}
getLength({x: 1, y: 2, z: 3})
The syntax is quite unique (although inspired by languages such as Rust or Scala), but has some similarities to the switch
statement we already know. Instead of the switch
keyword, we've got case
which marks the match beginning. Then, inside a block, we specify different patterns to check against using the when
keyword followed by a syntax similar to existent object destructuring. We can match against objects containing selected properties, against those properties' values and a lot more. For full details about possible matching capabilities check out the proposal explainer document.
After the pattern, you use "flat arrow" (->
) syntax pointing to an expression (potentially even other values) that should be evaluated when a certain pattern is matched.
From my point of view, having such functionality in JS would enable us to write some truly next-level code. However, I find the currently-proposed syntax a bit too verbose, as it introduces a lot of new constructs that weren't seen in the language before. And the fact that this feature is still at stage 1, leaves me thinking that there's some room for improvement. The feature is very promising, but it's still has a long way to go before it comes to the official specification.
Bottom line
This wraps up my list. There are a lot more of other ground-breaking feature proposals like an external standard library, or pipeline operator, but in this article, I cherry-picked only these few that I found interesting. Keep in mind that these are still only proposals and might change over time, or not actually implemented at all!. But if you want to be an early adopter anyway, I suggest you take a deeper look at projects like Babel, which bring many of these proposals to live (especially those that are only syntax-related) before they even ship, for you to play with them.
So, that's it! If you've got some personal best JS proposals at different stages, or are thinking of features that aren't even among them, be sure to share them down in the comment section below. And follow me on Twitter, Facebook, or through my weekly newsletter for more web development content. Thanks for reading and happy coding!
Top comments (0)