What’s Next for JavaScript? Top 5 new features for 2020!

By |2019-09-26T12:24:36-06:00September 27th, 2019|Articles, Insight Post, Technology, JavaScript|

JavaScript is one of the most popular programming languages in 2019, and ever since the release of ES6, we have seen amazing improvements with every new release. Now with the new year around the corner, I thought it would be fun to take a brief look and see some of the new features we have coming our way.

Here are my Top 5 most anticipated features for ES2020!

5. globalThis

If you have been working with JavaScript in both the front and back end for a little while, then there is a good chance that you have seen this error once or twice, ReferenceError: window is not defined. As you probably quickly realized this is because Node doesn’t have a global window property like the browsers. Instead, Node uses a property aptly named global to handle global functions and values. For example, if you would want to use the setTimeout function, you would need to write it differently depending on the environment.

Browser

window.setTimeout(() => console.log(‘Hi there friend!’),1000)

Node

global.setTimeout(() => console.log(‘Hi there friend!’),1000)

The above can be very annoying, especially if you want to use/build libraries across both environments or if you forget to use the appropriate keyword. Now you may have noticed that you could create a function to return the appropriate global object.

var getGlobal = function () {
   if (typeof self !== ‘undefined’) { return self; }
   if (typeof window !== ‘undefined’) { return window; }
   if (typeof global !== ‘undefined’) { return global; }
   throw new Error(‘unable to locate global object’);
 };
  var globals = getGlobal();
  if (typeof globals.setTimeout !== ‘function’) {
   // no setTimeout in this environment!
 }

Now the above would work, but you would need to make this function available everywhere in your code and if your site has CSP enabled this code may fail to run in the browser.

This is where globalThis comes in. If you need access to the global object, use globalThis. The above code can be rewritten as

globalThis.setTimeout(() => console.log(‘Hi there friend! I work Everywhere!’),1000)

Looks a lot better, and it can be used throughout the application, it’s important to note that you cannot use browser exclusive functions, i.e., alert(). However, this is still a nice feature that will undoubtedly help developers across the board, increasing the portability of their JS code.

4. Class Fields

JavaScript’s class declarations where a great addition to the language and helped bring a lot of C# and Java devs back to check it out. Now, this doesn’t mean it’s perfect, let’s take a look at how you initialize instance properties in JS.
Here is a simple Counter class with one instance property, count.

class Counter{
   increment(){
       this.count++
   }
   constructor(){
       this.count = 0
   }
}
const counter = new Counter()
counter.increment()
counter.increment()
console.log(counter.count) // 2

For those coming from a C# or Java, this may seem very confusing. The count property was declared and initialized in the constructor by setting the value to “this.” For many, this may seem a little unintuitive.
Class Fields help solve this problem.

class Counter{
   count = 0
   increment(){
       this.count++
   }
}

As you can see, count is declared and initialized as a field without the need to be declared in the constructor. That may not seem like much, but I am always excited about changes that help javascript become more self-documenting and make my life a bit easier.

3. Private class fields, methods, and accessors

Okay, sure class fields are a nice to have feature that helps with clarity, but private fields? Now we are starting to get into the significant changes! With this new feature, we will be able to declare properties, methods, accessors, and mutators as private. Let’s take this example of a person.

class Person{
   firstName =
   lastName =
   set fullName(x){
       const names = x.split(‘ ‘)
       this.firstName = names[0]
       this.lastName = names[1]
   }
   get fullName(){
       return `${this.firstName} ${this.lastName}`
   }
}
const person = new Person()
person.fullName = ‘John Smith’
console.log(person.fullName) // John Smith

As you can see, we can use getters and setters to set the name values, but we can also ignore them and set/get the firstName/lastName properties directly. That could be dangerous if they were only intended to be changed or accessed in specific ways, and it also makes it more difficult for the developers to know how the class was designed to be used.
Well without further ado here is the above example but with the new private operator.

class Person{
   #firstName =
   #lastName =
   set fullName(x){
       const names = x.split(‘ ‘)
       this.#firstName = names[0]
       this.#lastName = names[1]
   }
  
get fullName(){
       return `${this.#firstName} ${this.#lastName}`
   }
}
console.log(person.firstName) // undefined

Now if we wanted to get the person’s name, we would have to use the defined getter; using the private properties would return undefined. Also note that we can also make accessors, mutators, and methods private in the same way! Again another excellent feature for clarity and organization.

2. Promise.allSettled()

Promises have always had their quirks, but one of the most frustrating issues becomes apparent when you want to run multiple promises at once using Promise .all.
Normally it works great for waiting till all the promises have been completed successfully. However, if one of them fails, then the Promise.all call completes early with an error.

var promise1 = Promise.resolve(3);
var promise2 = new Promise(function(resolve,reject){
   setTimeout(resolve,1000,‘bar’)
});
var promise3 = new Promise(function(resolve, reject) {
 setTimeout(reject, 100, ‘foo’);
});
Promise.all([promise1, promise2, promise3]).then(function(values) {
 console.log(values);
});
//(node:30618) UnhandledPromiseRejectionWarning: foo
//(node:30618) UnhandledPromiseRejectionWarning: Unhandled promise rejection.

Obviously, this is no good in a lot of real-world scenarios. What if the site could still run without that failed call? Alternatively, what if multiple calls failed and you want to know which ones instead of just the first one. This is where Promise.allSettled() comes into the picture. In this context, a promise is considered “settled” once it returns regardless of status. So the above error code would return:

Promise.allSettled([promise1, promise2, promise3]).then(function(values) {
 console.log(values);
});
[
  { status: ‘fulfilled’, value: 3 },
  { status: ‘fulfilled’, value: ‘bar’ },
  { status: ‘rejected’, reason: ‘foo’ }
]

As you can see, we now get a status value for each Promise. Personally I have run into this issue many times, and I am thrilled that in future updates, I will no longer need to work around this issue and can rely on the native API. I don’t see myself using Promise.all much after this at all, unless there is a really compelling reason to use a failure short circuit.

1. Optional Chaining

Here it is, my personal number 1 feature! If you have worked with JavaScript for any extent of time, then you have seen this error when accessing an object’s properties TypeError: Cannot read property ‘*******’ of undefined

So to get around this error, you probably had to do something along the lines of this:

var street = user && user.address && user.address.street

I don’t know about you, but this is the bane of my existence. When moving between C# and JavaScript, the only thing that ever bothered me was having to write code that always felt tedious. Now finally there is light at the end of the tunnel! We can soon rewrite the above line as

var street = user?.address?.street

The basic rule is, If any of the values after a ? are null or undefined, then the statement will return null or undefined without throwing an error.
In this scenario, the user variable will be checked if it is null or undefined, followed by address, then finally it will return the value for street.
That was all done without having to copy and paste the same thing or create a bunch of temporary values! Now we can also take note that you don’t need to have the “?” operator at every level if you are confident that every user has an address but are concerned if user exists. Then you could use the following:

var street = user?.address.street

Also, since the statements will return null or undefined, you can optionally give default values using the || operator or the future null coalescing operator “??”.

var street = user?.address?.street || ‘default street’

I believe this feature will save every developer time and prevent a lot of unnecessary errors. Although simple, this feature is by far the one I see myself taking advantage of the most out of all the future proposals.

Conclusion

If any of these features seemed interesting, make sure to check out the tc39 GitHub where you can look through detailed explanations of all these future proposals and see how you can try them out now!
https://github.com/tc39/proposals

All right, that wraps up the list of my top 5 most anticipated features for ES2020, what do you guys think? Are there any features you think should have made it into the list? What’s your favorite feature, let us know in the comments below! Thanks for reading!