Since 2015, the JavaScript is evolving fast with lots of new features coming out in each iteration. New versions of the JavaScript language specification have been updated yearly, with new language feature proposals being finalized faster than ever.
This means that new features are getting incorporated into modern browsers and other JavaScript run-time engines like Node.js at a pace that we haven’t seen before. In 2019, there are many new features that are in the ‘Stage 3’ phase, which means that it’s very close to being finalized and browsers are getting support for these features now.
If we want to use them for production code, we can use something like Babel to transpile them to older versions of JavaScript so they can be used in older browsers like Internet Explorer if needed.
In this article, we’ll look at static fields and methods in classes and using the await
keyword at the top level in regular code and module exports.
Static Fields and Methods in Classes
Static fields in classes is a new feature that’s coming soon to browsers and Node.js. It lets us add static fields for classes that do not need an instance of the class to be created to be accessed. They can both be private or public. It’s a handy replacement for enums. For example, with the latest proposal, we can write a class with static variables like in the following example:
class Fruit {
static orange = 'orange';
static grape = 'grape';
static banana = 'banana';
static apple = 'apple';
static #secretPear = 'pear';
}
console.log(Fruit.orange);
console.log(Fruit.grape);
console.log(Fruit.banana);
console.log(Fruit.apple);
The example above should output:
orange
grape
banana
apple
If we try to access secretPear
from outside the class, like in the following code:
console.log(Fruit.#secretPear);
We’ll get ‘Uncaught SyntaxError: Private field ‘#secretPear’ must be declared in an enclosing class.’
The keyword static
is already working with methods in the classes since ES6. For example, we can declare a static method within a class by using the static
keyword like in the following code:
class ClassStatic {
static staticMethod() {
return 'Static method has been called.';
}
}
console.log(ClassStatic.staticMethod());
We should get ‘Static method has been called’ from the console.log
output. As we can see the staticMethod
method was called without instantiating the class ClassStatic
class just like we expected. Static methods can also be private, we just add a #
sign before the name of the method to make it private. For example, we can write the following code:
class ClassStatic {
static #privateStaticMethod(){
return 'Static method has been called.';
}
static staticMethod() {
return ClassStatic.#privateStaticMethod();
}
}
console.log(ClassStatic.staticMethod());
In the code above, we called the privateStaticMethod
from the staticMethod
to get the value of the return value from privateStaticMethod
in staticMethod
. Then when we call staticMethod
by running ClassStatic.staticMethod()
then we get ‘Static method has been called.’ However, we can’t call privateStaticMethod
directly from outside the class, so if we run something like:
class ClassStatic {
static #privateStaticMethod(){
return 'Static method has been called.';
}
static staticMethod() {
return ClassStatic.#privateStaticMethod();
}
}
console.log(ClassStatic.#privateStaticMethod());
Then we will get an error. Also, note that we aren’t using this
to access the privateStaticMethod
, we used the class name ClassStatic
to do it. If we use this
to call it, as in this.#privateStaticMethod()
, we’ll get an error or undefined
depending on the Babel version we’re using. The static
keyword for variables is partially supported within browsers. Chromium browsers like Chrome and Opera support it. Also, Node.js supports this keyword. Other browsers do not support it yet, so we’ve to use Babel to convert it into older JavaScript code for it to run on other browsers.
Top Level await
Currently, the await
keyword can only be used inside async
functions, which are functions that return promises. If we use the await
keyword outside of an async
function, we’ll get an error like ‘Cannot use keyword ‘await’ outside an async function’ and our program won’t run. Now we can use the await
keyword without it being inside an async
function. For example, we can use it with the following code:
const promise1 = new Promise((resolve)=>{
setTimeout(()=> resolve('promise1 resolved'), 1000);
})
const promise2 = new Promise((resolve)=>{
setTimeout(()=> resolve('promise2 resolved'), 1000);
})
const val1 = await promise1;
console.log(val1);
const val2 = await promise2;
console.log(val2);
Then when we run this code above in Chrome, we’ll get:
promise1 resolved
promise2 resolved
With top-level await
, we can run asynchronous code however we like, and we don’t have to go back to using the long-winded then
function chaining with callbacks passed into each then
function call. This is very clean and we don’t have to wrap it inside an async
IIFE (immediately invoked function expression) to run it if we don’t want to declare a named function.
Another good thing about top-level await
is that we can export it directly. This means that when the module exports something that has the await
keyword, it will wait for the promise being the await
keyword to resolve before running anything. On the surface, it acts as if it’s imported synchronously as usual, but underneath, it actually waits for the promise in the export
expression to resolve. For example, we can write:
const promise1 = new Promise((resolve)=>{
setTimeout(()=> resolve('promise1 resolved'), 1000);
})
export const val1 = await promise1;
When we import module1.js
in module2.js
:
import { val1 } from './module1';
console.log(`val1);
Then we can see the value of val1
logged as if it’s running synchronously, waiting for promise1
to resolve.
Conclusion
Static fields in classes is a new feature that’s coming soon to browsers and Node.js. It lets us add static fields for classes that do not need an instance of the class to be created to be accessed. They can both be private or public. It’s a handy replacement for enums.
Static methods have existed since ES6 and so it can be used now and has widespread support. Using the await
keyword at the top level in regular code and module exports is very handy once it’s a finalized feature. It lets us use await
to write asynchronous code outside of async
functions, which is much cleaner than using then
with callbacks.
Also, it can let us export the resolved value of asynchronous code and then import it and it use it in other modules as if it was synchronous code.