08 Aug 7 Exciting New JavaScript Features You Need to Know

JavaScript (or ECMA Script) is an evolving language with lots of proposals and ideas on how to move forward. TC39 (Technical Committee 39) is the committee responsible for defining JS standards and features, and they have been quite active this year. Here is a summary of some proposals that are currently in “Stage 3”, which is the last stage before becoming “finished”. This means that these features should be implemented in browsers and other engines pretty soon. In fact, some of them are available now.

1. Private fields #

Available in Chrome & NodeJS 12

Yes, you read that right. Finally, JS is getting private fields in classes. No more this._doPrivateStuff(), defining closures to store private values, or using WeakMap to hack private props.

2. Optional Chaining ?.

Ever had to access a property nested a few levels inside an object and got the infamous error Cannot read property 'stop' of undefined. Then you change your code to handle every possible undefined object in the chain, like:

JavaScript

1

2

3

4

5

6

conststop=please&&please.make&&please.make.it&&please.make.it.stop;

// or use a library like 'object-path'

conststop=objectPath.get(please,"make.it.stop");

We with optional chaining, soon you’ll be able to get the same done writing:

4. BigInt 1n

Available in Chrome & NodeJS 12

One of the reasons JS has always been terrible at Math is that we can’t reliably store numbers larger than 2 ^ 53, which makes it pretty hard to deal with considerably large numbers. Fortunately, BigInt is a proposal to solve this specific problem.

Without further ado

JavaScript

1

2

3

4

5

6

7

8

9

10

// can define BigInt by appending 'n' to a number literal

consttheBiggestInt=9007199254740991n;

// using the constructor with a literal

constalsoHuge=BigInt(9007199254740991);

// or with a string

consthugeButString=BigInt('9007199254740991');

You can also use the same operators on BigInt as you would expect from regular numbers, eg: +, -, /, *, %, … There’s a catch though, you can’t mix BigInt with numbers in most operations. Comparing Number and BigInt works, but not adding them

5. static Fields

Available in Chrome & NodeJS 12

This one is pretty straightforward. It allows having static fields on classes, similar to most OOP languages. Static fields can be useful as a replacement for enums, and they also work with private fields.

Another killer use case is that it can be used at the top level of ES modules that initialize in an async manner (think about your database layer establishing a connection). When such an “async module” is imported, the module system will wait for it to resolve before executing the modules that depend on it. This will make dealing with async initialization much easier than the current workarounds of returning an initialization promise and waiting for it. A module will not know whether its dependency is async or not.

JavaScript

1

2

3

4

// db.mjs

export constconnection=await createConnection();

JavaScript

1

2

3

4

5

6

// server.mjs

import{connection}from'./db.mjs';

server.start();

In this example, nothing will execute in server.mjs until the connection is complete in db.mjs.

7. WeakRef

Available in Chrome & NodeJS 12

A weak reference to an object is a reference that is not enough to keep an object alive. Whenever we create a variable with (const, let, var) the garbage collector (GC) will never remove that variable from memory as long as it’s reference is still accessible. These are all strong references. An object referenced by a weak reference, however, may be removed by the GC at any time if there is no strong reference to it. A WeakRef instance has a method deref which returns the original object referenced, or undefined if the original object has been collected.

This might be useful for caching cheap objects, where you don’t want to keep storing all of them in memory forever.

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

constcache=newMap();

constsetValue=(key,obj)=>{

cache.set(key,newWeakRef(obj));

};

constgetValue=(key)=>{

constref=cache.get(key);

if(ref){

returnref.deref();

}

};

// this will look for the value in the cache

// and recalculate if it's missing

constfibonacciCached=(number)=>{

constcached=getValue(number);

if(cached)returncached;

constsum=calculateFibonacci(number);

setValue(number,sum);

returnsum;

};

This is probably not a good idea for caching remote data as it can be removed from memory unpredictably. It’s better to use something like an LRU cache in that case.